【问题标题】:Idiomatically negate a filter惯用地否定过滤器
【发布时间】:2015-03-08 03:36:47
【问题描述】:

用否定写filter 最惯用的方法是什么?

例子:

is_even= lambda x : x % 2 == 0
odd_numbers= filter( lambda x: not is_even(x), range(10) )

当然,您可以只使用列表推导式 - 但无论如何您都不需要使用 filter

如果有人想知道,我在尝试split a list based on a condition时偶然发现了这个

【问题讨论】:

  • 如果有人想知道,我正在尝试split a list based on a condition
  • 那位小姐) 是错字吗?
  • 该死,你在我发帖后 1 秒编辑了它。太快了:P ..
  • 你能告诉我们你真正想要做什么吗?请进行更广泛的描述。您发布的内容有什么问题?
  • @ReutSharabani 我在 cmets 中提到了这一点,但我会将其移至问题本身。我写的没有什么,我只是想知道是否有更惯用或更简洁的方式来做到这一点

标签: python filter functional-programming negation


【解决方案1】:

itertools 模块包括ifilter()ifilterfalse(),它们分别过滤函数返回TrueFalse 的元素。

odd_numbers = ifilterfalse(is_even, range(10))

请注意,在 Python 2 中,filterifilter 之间存在差异:odd_numbers 将是一个迭代器,而 filter() 将给出一个列表(参见 itertools.ifilter Vs. filter Vs. list comprehensions)。如果您真的想建立一个列表,那么您使用not 的示例似乎很好,假设您已设置使用filter - 列表推导可能更“惯用”(List filtering: list comprehension vs. lambda + filter)。

在 Python 3 中,filter() 构造一个迭代器,而不是一个列表,itertools.filterfalse() 是补码。

【讨论】:

  • 有谁知道为什么作者选择ifilterfalse而不是ireject
【解决方案2】:

基于谓词的拆分称为partition。我会发现将partition 实现为一个单独的函数而不是专门针对奇数和偶数重复其内部结构更为惯用。 Python 3 的Itertools Recipes 具有以下实现:

def partition(pred, iterable):
    'Use a predicate to partition entries into false entries and true entries'
    # partition(is_odd, range(10)) --> 0 2 4 6 8   and  1 3 5 7 9
    t1, t2 = tee(iterable)
    return filterfalse(pred, t1), filter(pred, t2)

它使用该模块中定义的filterfalse(如@Lack 所述)和tee。因此,您的最高级别代码如下所示:

odds, evens = partition(is_even, range(10))

【讨论】:

  • 是的,如果您同时使用列表的两个部分,这是解决实际问题的更好方法。
  • 这可能值得在我链接的问题中发布,因为还没有人提到它。尤其是我的问题更多是出于好奇,而不是解决实际分区的实际需要(已经有很多答案)
猜你喜欢
  • 2012-03-29
  • 2017-10-19
  • 1970-01-01
  • 2012-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多