假设我有一个执行大量计算的函数。
def f(x):
...
return result
然后我有一个列表,其中包含我想要传递给f()
的值:
my_list = [2, 98, 4, 34, 23, 11]
我想在此列表中找到第一个元素x
,用于验证f(x)
上的条件(让我们说例如f(x) != 0
),并获得此计算结果
基本上,我会像这样写一个for
循环:
def first_match(my_list):
for x in my_list:
r = f(x)
if r != 0:
return r
我想知道是否有办法使用生成器表达式获得相同的结果?
到目前为止我的想法是这样的:
r = next(f(x) if f(x) != 0 for x in my_list)
问题是这会两次调用f()
。
答案 0 :(得分:5)
您可以使用嵌套的生成器表达式来避免双重函数调用:
Application
答案 1 :(得分:4)
有一种方法可以使用生成器表达式,already mentioned为Blckknght,但问题中的first_match()
函数也没有错。并非所有事情都必须是单行代码:)。
以下是另一种方法:
try:
from itertools import ifilter as filter # Python 2
except ImportError:
pass # Python 3
predicate = lambda x: x != 0
r = next(filter(predicate, (f(x) for x in my_list)), None)
next()
(上面代码中的None
)的第二个参数是,如果迭代器中没有任何内容作为第一个参数传入,则返回什么。如果您没有指定它并且迭代器已用尽,则会引发StopIteration
异常。您可以将其更改为您想要的任何内容。
答案 2 :(得分:1)
from itertools import ifilter
next(ifilter(lambda x: f(x) != 0, my_list))
答案 3 :(得分:1)
理解可能是嵌套的地图功能,可选择过滤输入。在这种情况下,您希望过滤输出,因此请执行此操作。令y = f(x)= x x并且令c(y)=(y> 100)。然后(y为y in(x x代表my_list中的x),如果y> 100)给出滤波后的输出。正如您所注意到的那样,可以使用next来完成对第一个真元素(第一个真实搜索)的过滤器停止。
my_list = [2, 98, 4, 34, 23, 11]
ge = (y for y in (x*x for x in my_list) if y > 100)
print(next(ge))
# 9604
答案 4 :(得分:0)
通常,生成器表达式可以构造为生成器函数。例如,这个f(x)具有延迟评估,正如您对生成器所期望的那样:
perl -e 'exit(65280)'
echo $? # returns 0
是的,这是一个空委托,但你的例子可以用于你的功能(我不明白这样做的意图没有猜测)。