[python] 从符合条件的迭代中获取第一个项目


Answers

作为可重用,记录和测试的功能

def first(iterable, condition = lambda x: True):
    """
    Returns the first item in the `iterable` that
    satisfies the `condition`.

    If the condition is not given, returns the first item of
    the iterable.

    Raises `StopIteration` if no item satysfing the condition is found.

    >>> first( (1,2,3), condition=lambda x: x % 2 == 0)
    2
    >>> first(range(3, 100))
    3
    >>> first( () )
    Traceback (most recent call last):
    ...
    StopIteration
    """

    return next(x for x in iterable if condition(x))
Question

我想从符合条件的列表中获取第一项。 生成的方法不处理整个列表非常重要,该列表可能非常大。 例如,以下功能就足够了:

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

但是,我想不出一个好的内置/单线程来让我这样做。 如果我不需要,我不特别想复制这个功能。 有没有一种内置的方式来获得匹配条件的第一个项目?




在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



通过使用

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

可以检查_iterable中第一个项目的条件 ,并获取其索引,而无需评估_iterable中的所有项目。

要使用的完整表达式是

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

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




该死的例外!

我喜欢这个答案 。 但是,由于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



这个问题已经有了很好的答案。 我只是增加了我的两分钱,因为我登陆这里试图找到解决我自己的问题的方法,这与OP非常相似。

如果您想使用生成器查找符合条件的第一个项目的INDEX,则可以简单地执行:

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



itertools模块包含迭代器的过滤器函数。 过滤迭代器的第一个元素可以通过调用next()来获得:

from itertools import ifilter

print ifilter((lambda i: i > 3), range(10)).next()



Links