可能重复:
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])
答案 0 :(得分:10)
您可以合并ifilter
和islice
来获取第一个匹配元素。
>>> 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
是有效的返回值)。