python matplotlib设置坐标轴刻度大小 - 从符合条件的迭代中获取第一个项目




7 Answers

在Python 2.6或更高版本中:

如果您希望在找到没有匹配元素的情况下引发StopIteration

next(x for x in the_iterable if x > 3)

如果你想要返回default_value (例如None ):

next( (x for x in the_iterable if x>3), default_value)

请注意,在这种情况下,在生成器表达式周围需要一对额外的括号 - 当生成器表达式不是唯一参数时,它们总是需要。

我看到大多数答案坚决地忽略了next内置模块,所以我认为出于某种神秘的原因,他们100%专注于版本2.5和更高版本 - 没有提到Python版本问题(但是我没有看到提及的内容在提到next内置的答案中,这就是为什么我认为有必要自己提供答案 - 至少“正确版本”问题是这样记录的;-)。

在2.5中,迭代器的.next()方法立即引发StopIteration如果迭代器立即完成 - 即,对于您的用例,如果迭代器中没有项目满足条件。 如果你不在意(即,你知道必须至少有一个令人满意的项目),那么只需使用.next() (最好在Genexp中,为Python 2.6中的next内置行提供更好的内容)。

如果你真的关心,把函数包装成你在Q中第一次指出的函数似乎是最好的,虽然你提出的函数实现很好,但你也可以使用itertoolsfor...: break循环或者genexp ,或者try/except StopIteration作为函数的正文,因为提出了各种答案。 这些替代品中没有太多附加价值,所以我会选择你首次提出的非常简单的版本。

matplotlib标注 plot虚线

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

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

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




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

>>> (x for x in xrange(10) if x > 5).next()
6

无论哪种情况,您可能都希望捕获StopIteration ,以防万一没有元素满足您的条件。

从技术上讲,我想你可以做这样的事情:

>>> foo = None
>>> for foo in (x for x in xrange(10) if x > 5): break
... 
>>> foo
6

这将避免必须try/except块。 但是对于语法来说,这看起来很模糊和滥用。




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

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



我会写这个

next(x for x in xrange(10) if x > 3)



既然你已经请求了一个内置的单线程,这将避免StopIteration异常的问题,尽管它需要你的迭代器很小,所以你可以把它转换成一个列表,因为这是我知道的唯一的结构将吞下StopIteration并让你看看这些值:

(lambda x:x[0] if x else None)(list(y for y in ITERABLE if CONDITION))

(如果没有元素匹配,您将得到None而不是StopIteration异常。)




Python 3中最有效的方式是以下方法之一(使用类似的例子):

“理解”风格:

next(i for i in range(100000000) if i == 1000)

警告 :该表达式也适用于Python 2,但在该示例中使用的range是返回Python 3中的可迭代对象而不是Python 2之类的列表(如果要在Python 2中构建一个迭代器,请改用xrange )。

请注意,该表达式避免在理解表达式next([i for ...])构造列表,这会导致在过滤元素之前创建包含所有元素的列表,并导致处理整个选项停止迭代一次i == 1000

具有“功能性”风格:

next(filter(lambda i: i == 1000, range(100000000)))

警告 :这在Python 2中不起作用,甚至用xrange替代range ,因为filter创建了一个列表而不是迭代器(效率低下),而next函数只能用于迭代器。

默认值

正如其他响应中提到的,如果您希望避免在条件未满足时引发的异常,则必须为该函数添加一个额外参数。

“功能性”风格:

next(filter(lambda i: i == 1000, range(100000000)), False)

“理解”风格:

使用这种风格,您需要用()来包围理解表达式以避免SyntaxError: Generator expression must be parenthesized if not sole argument

next((i for i in range(100000000) if i == 1000), False)



Oneliner:

thefirst = [i for i in range(10) if i > 3][0]

如果您不确定任何元素根据条件是否有效,那么您应该try/except因为[0]会引发IndexError




Related

python iterator