我想从匹配条件的列表中获得第一项。产生的方法不能处理整个列表,这一点很重要,因为列表可能相当大。例如,以下函数就足够了:
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中最有效的方法是以下方法之一(使用类似的示例):
“理解”风格:
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,因为过滤器创建了一个列表而不是迭代器(效率低),下一个函数只适用于迭代器。
默认值
正如在其他响应中提到的那样,如果希望避免在条件不满足时引发异常,则必须向接下来的函数添加一个额外参数。
“功能性”风格:
next(filter(lambda i: i == 1000, range(100000000)), False)
“理解”风格:
使用这种风格,你需要用()包围理解表达式,以避免SyntaxError:如果不是唯一的参数,生成器表达式必须用圆括号括起来:
next((i for i in range(100000000) if i == 1000), False)
下面是带有基准的3个备选方案。
使用next ()
一行程序:
values = list(range(1, 10000000))
value = next((x for x in values if x > 9999999), None)
使用函数
这是使用函数next()的替代方案,它大约快2%-5%:
values = list(range(1, 10000000))
def first(items):
for item in items:
if item > 9999999: # Your condition
return item
return None # Default value
value = first(values)
使用λ
这是一个在所有情况下都可用于替换next()的函数。性能大约降低300%:
values = list(range(1, 10000000))
def first(items, condition, default = None):
for item in items:
if condition(item):
return item
return default
value = first(values, lambda x: x > 9999999, None)
基准
功能:1 x
下:1.02 - 1.05 x
Lambda: > 3x
内存消耗相同。
这就是基准。
如果你不想使用next(),你可以使用unpacking:
>>> a, *_ = filter(lambda e: e == 10, [7,8,9,10,11,12])
>>> a
10
>>> _
[]
>>> a, *_ = filter(lambda e: e == 1000, [7,8,9,10,11,12])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: not enough values to unpack (expected at least 1, got 0)
注意,使用filter()相当于写入Python Docs (item for item in iterable if condition)。
如果你需要对边缘情况的支持,你可以这样写:
>>> a, *_ = [e for e in [7,8,9,10,11,12] if e == 1000] or [None]
>>> a
None
>>> _
[]