我正在寻找类似的东西:
foo = [ p for p in somelist if xxx(p)][0:10]
这可行,但在所有列表上执行xxx,xxx很昂贵。
我可以编写一个子函数,例如
def blah (list, len):
res=[]; i=0;
while i<len:
if xxx(list[i]):
res.append(i)
return res
但这似乎非常不合情理。
证明第一个结果的例子是错误的:
foo = [ p for p in (1,2,3,4,5,0,6) if 100/p ][0:3]
哪个“应该”返回[1,2,3]但实际上在除以零时失败。
我已经尝试过itertools的各种工具但找不到在达到大小后停止执行迭代器的组合。
答案 0 :(得分:2)
from itertools import islice
foo = list(islice((p for p in (1,2,3,4,5,0,6) if 100/p), 4))
请注意缺少括号:这是generator comprehension
答案 1 :(得分:1)
这与列表推导无关,但可以通过生成器理解来实现。
两者有什么区别?列表推导将一次迭代迭代,并根据您对iterable上项目的操作将列表返回给您。这里的关键是 all all 。
您的示例使用列表推导,然后会发生什么:首先评估列表推导。在你的情况下,它会失败,但即使它没有失败,它也会迭代迭代somelist
中的所有内容,并且会返回结果列表。然后将此列表切片并返回新的结果列表。
发电机理解和发电机一般有不同的工作方式。它们基本上是暂停的代码块,直到您从它们请求更多数据,这是您真正想要做的。
实际上,您可以按如下方式创建生成器:
g = (p for p in (1,2,3,4,5,0,6) if 100/p )
根据&#34;规则&#34>您现在有一个生成器,当您请求时,它将为您生成值。你给了它。
只要您手头有一台发电机,就可以通过多种方式从中获取n
项目。
您可以按如下方式编写一个简单的for循环:
results = []
for x in range(3): # n = 3 in your case
results.append(next(g))
当然,这不是Pythonic。假设您想要一个列表,您现在可以使用列表解析:
results = [next(g) for x in range(3)]
这是&#34;手册&#34;这样做的方式。您还可以使用islice
模块(Documentation here)中的itertools
函数:
import itertools
results = list(itertools.islice(g, 4))
就是这样。生成器非常有用。在请求并记住其状态时执行的代码块是非常宝贵的。
答案 2 :(得分:0)
通过使用内置过滤器和islice的组合,您可以实现您想要的效果。 例如
length = 3
items_iter = islice(filter(None, [1, 2, 0, 4, 5]), length) # returns a lazy iterator
items = list(items_iter)
assert items == [1, 2, 5]
但是,您可能希望编写自己的生成器。生成器函数将生成连续项,而不是返回单个结果。有时它可能不会产生任何物品,有时它们会产生无限数量的物品。以下是您的案例示例:
def take_first_n_that_pass(test, length, iterator):
i = 0
for item in iterator:
if i >= length:
return # stops generator
if test(item):
yield item
i += 1
# end of iterator -- generator stops here as well
items_iter = take_first_n_that_pass(bool, 3, [0, 1, 2, 0, 4, 5])
items = list(items_iter)
assert items == [1, 2, 4]