【问题标题】:Python - dynamic filter for list comprehension?Python - 用于列表理解的动态过滤器?
【发布时间】:2017-11-01 15:38:16
【问题描述】:

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

现在我的方法是这样的:

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,即使我只需要不同的运算符,我也总是需要指定整个函数。

【问题讨论】:

  • 我不太明白你想要什么。 lambda 函数 运算符,不是吗?还是您的意思是“不在”替换“在”?是的,您可以对其进行参数化,但这可能比您想要的更麻烦。您希望该功能有多通用?您需要什么范围的控制?
  • @Prune 控制操作员会很好(如in not in 等)。使用 lambda,它可能是通用的,因为我可能不需要那么多控制。

标签: python python-2.7 filter list-comprehension


【解决方案1】:

例如使用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]
>>> 

这是因为equals的异或结果为假,不同的异或结果为真

【讨论】:

  • 您可以更进一步,通过使用 getattr 或使用类似 sorted 的关键函数从对象中提取您想要的任何属性来过滤任何属性跨度>
  • 事实上,我就是这样实现的:)
【解决方案2】:
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))编写它允许您为“排除”传递任意真/假值,而不仅仅是真或假。

【讨论】:

  • 这和稍微简洁一点的[obj for obj in objects if (obj.name in names) != exclude]一样吗?不确定not 是否做了一些!= 没有做的评估
  • 只有当exclude 是一个正确的布尔值(TrueFalse)时才有效。 not 是强制产生这种结果的最简单方法。
  • Riiight,所以传入一个空列表[] 作为False 的替代仍然可以与== (not exclude) 一起使用?
【解决方案3】:

现在我将采用这种方法。它有点有限,但它可以满足我目前的需要。

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)]

附:我放弃了operator 库,因为使用任何一种方式都受到限制的功能,不需要operator 库。

【讨论】:

    【解决方案4】:

    从 Python operators 开始。 containsnot 应该足以为您提供所需的控制。但是,这将比您当前的代码略短,并且结果更难阅读。另一方面,这应该会给你很多关于下一步要配置什么的好主意。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-06-09
      • 2011-03-02
      • 1970-01-01
      • 1970-01-01
      • 2011-12-17
      • 1970-01-01
      相关资源
      最近更新 更多