我想从匹配条件的列表中获得第一项。产生的方法不能处理整个列表,这一点很重要,因为列表可能相当大。例如,以下函数就足够了:

def first(the_iterable, condition = lambda x: True):
    for i in the_iterable:
        if condition(i):
            return i

这个函数可以这样使用:

>>> first(range(10))
0
>>> first(range(10), lambda i: i > 3)
4

但是,我想不出一个好的内置/单行程序来让我这样做。如果没有必要,我不想复制这个函数。是否有一种内置的方法来获取匹配条件的第一项?


当前回答

这个问题已经有了很好的答案。我只是说说我的意见,因为我来这里是想为我自己的问题找到一个解决方案,这和OP非常相似。

如果你想使用生成器找到匹配条件的第一项的INDEX,你可以简单地这样做:

next(index for index, value in enumerate(iterable) if condition)

其他回答

对于不存在下一个内置的旧版本的Python:

(x for x in range(10) if x > 3).next()

在Python 3中:

a = (None, False, 0, 1)
assert next(filter(None, a)) == 1

在Python 2.6中:

a = (None, False, 0, 1)
assert next(iter(filter(None, a))) == 1

编辑:我认为这是显而易见的,但显然不是:而不是None,你可以传递一个函数(或一个lambda),检查条件:

a = [2,3,4,5,6,7,8]
assert next(filter(lambda x: x%2, a)) == 3

对于任何使用Python 3.8或更新版本的人,我建议使用PEP 572—赋值表达式中描述的“赋值表达式”。

if any((match := i) > 3 for i in range(10)):
    print(match)

通过使用

(index for index, value in enumerate(the_iterable) if condition(value))

可以检查the_iterable中第一项的值的条件,并获得它的索引,而不需要计算the_iterable中的所有项。

要使用的完整表达式是

first_index = next(index for index, value in enumerate(the_iterable) if condition(value))

这里first_index假设上面讨论的表达式中标识的第一个值的值。

该死的例外!

我喜欢Alex Martelli的回答。然而,由于next()在没有项目时抛出StopIteration异常, 我会使用下面的代码片段来避免异常:

a = []
item = next((x for x in a), None)

例如,

a = []
item = next(x for x in a)

将引发StopIteration异常;

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration