简体   繁体   English

一般使用lambda函数作为字符串过滤Python对象数组中的值

[英]Filter values in a Python object array generically with a lambda function as a string

I'm working on a generic framework, and at some point I'm trying to filter variables in a generic manner. 我正在研究一个通用框架,在某些时候我试图以通用的方式过滤变量。 Take for example the following class: 以下面的课程为例:

class X:
    def __init__(self, val):
        self.val = val

Then I have an array of objects with arbitrary val values: 然后我有一个具有任意val值的对象数组:

arr = [X("1"), X("2"), X("2"), X("3"), X("foo"), X("5"), X("3")]

My goal is to have a function which takes a lambda function and a variable names as strings (because they are user provided), which is currently implemented as follows: 我的目标是有一个函数,它将lambda函数和变量名称作为字符串 (因为它们是用户提供的),目前实现如下:

def process(lambda_f_str, var_str):
    # should return [1, 2, 3, 5]
    return list(set(filter(lambda x: x, map(eval(lambda_f_str), eval(var_str)))))

I want to be able to call this method with a given lambda function string that will return me only the unique integer values of these objects (In this example I'd expect [1 2 3 5] , the order doesn't matter). 我希望能够使用给定的lambda函数字符串调用此方法,该字符串将仅返回这些对象的唯一整数值​​(在此示例中,我期望[1 2 3 5] ,顺序无关紧要)。

I've tried something like this: 我尝试过这样的事情:

process("lambda x: x.val if isinstance(x.val, int) else None", "arr")

But this doesn't work since the integers are still passed as strings in my array (and I have no control over that, this is user-provided so I can't make any assumption). 但这不起作用,因为整数仍然作为我的数组中的字符串传递(我无法控制它,这是用户提供的所以我不能做任何假设)。

I wanted to do the equivalent of 我想做相同的

try:
    int(x)
except:
    # do something if not an int

But I don't think you can do that in a lambda function ... can you? 但我认为你不能用lambda函数做到这一点......你呢? At least I haven't found out how. 至少我还没有发现如何。

I'd be interested to see how I can write this lambda to do this filtering in a generic manner. 我有兴趣看看如何编写这个lambda来以通用的方式进行这种过滤。 I'd rather avoid changing the process method since this is a generic function which does other things not included in this sample code for the sake of brevity. 我宁愿避免更改process方法,因为这是一个通用函数,为了简洁起见,它会执行此示例代码中未包含的其他内容。

Try this... 尝试这个...

s = "lambda x: int(x.val) if x.val.isdigit( ) else None"
print process(s, "arr")

I get back... 我回来了......

[1, 2, 3, 5] [1,2,3,5]

Note that the .isdigit( ) method will fail if the numbers are given with commas or decimals. 请注意,如果数字以逗号或小数表示,则.isdigit( )方法将失败。

Do you really need the evals? 你真的需要逃避吗?

f = lambda x: x.val if isinstance(x.val, int) else (int(x.val) if isinstance(x.val, basestring) and x.isdigit() else None)

Not 100% proof, eg it doesn't take 123L which is valid Python. 不是100%证明,例如它不需要123L这是有效的Python。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM