如何找到与Python中的谓词匹配的序列中的第一个元素?

时间:2012-10-17 07:08:59

标签: python python-3.x functional-programming

  

可能重复:
  Python: find first element in a sequence that matches a predicate

Python标准库中是否有更高阶的函数来封装以下控制流模式?

>>> def find(pred, coll):
...   for x in coll:
...     if pred(x):
...       return x
... 
>>> find(lambda n : n % 2 == 0, [3, 5, 8, 9, 6])
8
>>> find(lambda n : n % 2 == 0, [3, 5, 7, 9, 6])
6
>>> find(lambda n : n % 2 == 0, [3, 5, 7, 9, 1])

4 个答案:

答案 0 :(得分:10)

您可以合并ifilterislice来获取第一个匹配元素。

>>> list(itertools.islice(itertools.ifilter(lambda n: n % 2 == 0, lst), 1))
[8]

但是,我不会认为这比您发布的原始代码更具可读性或更好。包含在一个函数中它会更好。由于next只返回一个元素,因此不再需要islice

def find(pred, iterable):
    return next(itertools.ifilter(pred, iterable), None)

如果未找到任何元素,则返回None

但是,每个循环仍然会调用谓词函数。请考虑使用列表推导或生成器表达式:

>>> next((x for x in lst if x % 2 == 0), None)
8

答案 1 :(得分:4)

itertools.ifilter()可以执行此操作,如果您只是抓取生成的可迭代的第一个元素。

itertools.ifilter(pred, col1).next()

同样,生成器对象也是如此(同样,从生成的生成器中取出第一个项目):

(i for i in col1 if i % 2 == 0).next()

由于这两个都是惰性求值的,因此您只需要评估尽可能多的输入迭代,以获得满足谓词的第一个元素。请注意,如果没有任何内容与谓词匹配,则会出现StopIteration异常。您可以使用next()内置来避免这种情况:

next((i for i in col1 if i % 2 == 0), None)

答案 2 :(得分:1)

我不知道我的头顶有这样的功能,但你可以使用生成器表达式并取第一个结果。

x = (x for x in [3,5,8,9,6] if (lambda n: n % 2 == 0)(x))
y = x.next()

或者只是

y = (x for x in [3,5,8,9,6] if (lambda n: n % 2 == 0)(x)).next()

答案 3 :(得分:1)

(x for x in coll if pred(x)).next()

如果找不到该项,则引发StopIteration(这可能比返回None更可取,特别是如果None是有效的返回值)。