首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >从符合条件的迭代器中获取第一项

从符合条件的迭代器中获取第一项
EN

Stack Overflow用户
提问于 2010-03-02 15:11:30
回答 12查看 271.5K关注 0票数 420

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

代码语言:javascript
复制
def first(the_iterable, condition = lambda x: True):
    for i in the_iterable:
        if condition(i):
            return i

此函数的用法如下所示:

代码语言:javascript
复制
>>> first(range(10))
0
>>> first(range(10), lambda i: i > 3)
4

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

EN

回答 12

Stack Overflow用户

发布于 2016-02-20 03:25:41

作为一个可重用的、有文档记录和测试过的功能

代码语言:javascript
复制
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))

带有默认参数的版本

@zorf建议了此函数的一个版本,如果可迭代为空或没有匹配条件的项,则可以使用预定义的返回值:

代码语言:javascript
复制
def first(iterable, default = None, 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.

    If the `default` argument is given and the iterable is empty,
    or if it has no items matching the condition, the `default` argument
    is returned if it matches the condition.

    The `default` argument being None is the same as it not being given.

    Raises `StopIteration` if no item satisfying the condition is found
    and default is not given or doesn't satisfy the condition.

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

    try:
        return next(x for x in iterable if condition(x))
    except StopIteration:
        if default is not None and condition(default):
            return default
        else:
            raise
票数 40
EN

Stack Overflow用户

发布于 2010-03-02 15:27:51

与使用ifilter类似,您可以使用生成器表达式:

代码语言:javascript
复制
>>> (x for x in xrange(10) if x > 5).next()
6

在这两种情况下,您都可能希望捕获StopIteration,以防没有元素满足您的条件。

从技术上讲,我认为你可以这样做:

代码语言:javascript
复制
>>> foo = None
>>> for foo in (x for x in xrange(10) if x > 5): break
... 
>>> foo
6

它可以避免创建try/except块。但这对语法来说似乎有些晦涩和滥用。

票数 13
EN

Stack Overflow用户

发布于 2010-03-02 16:22:09

我会写这篇文章

代码语言:javascript
复制
next(x for x in xrange(10) if x > 3)
票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2361426

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档