Python - 用于列表理解的动态过滤器?

时间:2017-05-31 17:43:12

标签: python python-2.7 filter list-comprehension

我想编写一个方法来过滤给定的对象列表,具体取决于提供哪些运算符或函数来过滤。

现在我的方法看起来像这样:

def filter_by_names(objects, names, exclude=False):
    if exclude:
        return [obj for obj in objects if obj.name not in names]
    else:
        return [obj for obj in objects if obj.name in names]

现在它有两个过滤器选项,如果对象的名称在提供的名称列表中,则返回对象,或者执行相反的操作:返回名称不在提供的名称列表中的对象。

我想要的是能够动态指定如何过滤。我虽然使用了operator库,但似乎没有not in运算符,所以我需要将innot结合起来,这有点笨拙。

我在考虑使用lambda:

def filter_by_names(objects, names, fun=lambda obj, names: obj.name in names):
    return [obj for obj in objects if fun(obj, names)]

这个可行,但我想知道可能有更好的方法来做这样的事情?使用lambda我总是需要指定整个函数,即使我只需要不同的运算符。

4 个答案:

答案 0 :(得分:2)

如何使用xor运算符,例如

>>> n = range(0,11,2)
>>> n
[0, 2, 4, 6, 8, 10]
>>> exclude = True
>>> [ x for x in range(10) if (x in n) ^ exclude ] # only the one that are not in n
[1, 3, 5, 7, 9]
>>> exclude = False
>>> [ x for x in range(10) if (x in n) ^ exclude ] # only the one that are also in n
[0, 2, 4, 6, 8]
>>> 

这项工作是因为等于的xor导致为false,而不同的xor导致为真

答案 1 :(得分:1)

def filter_by_names(objects, names, exclude=False):
    return [obj for obj in objects if (obj.name in names) == (not exclude)]

使用not exclude(而不是(obj.name not in names) == exclude))来写这个内容,可以为'排除'传递任意的真值/假值,而不仅仅是真或假。

答案 2 :(得分:0)

从Python operators开始。 containsnot应足以为您提供所需的控制权。但是,这将比您当前的代码短得多,结果更难以阅读。另一方面,这应该会为您提供关于下一步要配置的许多可爱的想法。

答案 3 :(得分:0)

现在我采用这种方法。它有点受限,但它确实是我目前所需要的。

def filter_by_names(objects, names, exclude=False):

    def _filter(names, name):
        if exclude:
            return name not in names
        return name in names

    return [obj for obj in objects if _filter(names, obj.name)]

P.S。我删除了operator库,因为使用受限于任何方式的函数,不需要operator库。