我想通过一个迭代器反复遍历一个列表(N次),以免在列表中实际存储N个列表副本。有没有内置或优雅的方式来做到这一点,而不写我自己的发电机?是否有一种优雅的方式通过迭代遍历列表N次(如itertools.cycle但限制循环)?
理想情况下,itertools.cycle(my_list)将有第二个参数来限制它循环的次数...唉,没有这样的运气。
我想通过一个迭代器反复遍历一个列表(N次),以免在列表中实际存储N个列表副本。有没有内置或优雅的方式来做到这一点,而不写我自己的发电机?是否有一种优雅的方式通过迭代遍历列表N次(如itertools.cycle但限制循环)?
理想情况下,itertools.cycle(my_list)将有第二个参数来限制它循环的次数...唉,没有这样的运气。
import itertools
itertools.chain.from_iterable(itertools.repeat([1, 2, 3], 5))
Itertools是一个奇妙的图书馆。 :)
这是一个相当明确的答案,不涉及我自己的生成器/迭代器(尽管马特安德森的回答显示这不是太混乱),并且是一个满足我的问题的第一个答案。所以,我接受它。谢谢!! – JJC 2012-04-26 08:57:02
itertools.chain.from_iterable(iter(L) for x in range(N))
对于需要多次迭代列表的特殊情况,这并不算太坏。
它确实创造n
引用列表来my_list
,所以如果n
是非常大的,最好是用Darthfelt的回答
>>> import itertools as it
>>> it.chain(*[my_list]*n)
我试图避免在内存中复制列表(或引用它),否则只是:mylist * n将会是足够的。 :-)尽管如此,感谢您的意见。只需要清楚,通过* list运算符扩展列表并将其乘以n而不是将列表乘以n?是否有区别? – JJC 2012-04-26 13:34:52
@JJC,'mylist * n'用'len(mylist)* n)'元素创建一个列表。对于这个答案,你只需创建一个'n'元素列表,所以根据'len(mylist)'和'n',这可能会产生巨大的差异 – 2012-04-26 22:08:05
我明白[1,2,3,4] * 2会创建一个8个元素的列表。那么,你说* [1,2,3,4] * 2只创建了两个元素?对不起,我很困惑。谢谢。 – JJC 2012-04-28 09:36:19
其他所有的答案都非常优秀。另一种解决方案是使用islice
。这使您可以在任何时候中断周期:
>>> from itertools import islice, cycle
>>> l = [1, 2, 3]
>>> list(islice(cycle(l), len(l) * 3))
[1, 2, 3, 1, 2, 3, 1, 2, 3]
>>> list(islice(cycle(l), 7))
[1, 2, 3, 1, 2, 3, 1]
你说你不想写自己的发电机,但发电机表达式很可能会完成你”最简单,最有效的方法重新过后。它不需要任何函数调用或任何模块的导入。 itertools
是一个很好的模块,但在这种情况下可能不需要?
some_list = [1, 2, 3]
cycles = 3
gen_expr = (elem for _ in xrange(cycles) for elem in some_list)
或只是
(elem for _ in xrange(3) for elem in [1, 2, 3])
或
for elem in (e for _ in xrange(3) for e in [1, 2, 3]):
print "hoo-ray, {}!".format(elem)
我喜欢这些生成器表达式。它们比我意识到它们适合这种模式更紧凑。我将答案归功于@Darthfett,因为技术上我要求一个非自动滚动的发电机,但是如果我可以接受两个发电机,我也会接受你的(也可能是别人的:-))谢谢! – JJC 2012-04-26 08:52:50
@ Darthfett的答案被记录为一个itertools recipes:
from itertools import chain, repeat
def ncycles(iterable, n):
"Returns the sequence elements n times"
return chain.from_iterable(repeat(tuple(iterable), n))
list(ncycles(["a", "b"], 3))
# ['a', 'b', 'a', 'b', 'a', 'b']
为了方便,我补充一点,more_itertools
库实现这个配方(和许多其他)为你:
import more_itertools as mit
list(mit.ncycles(["a", "b"], 3))
# ['a', 'b', 'a', 'b', 'a', 'b']
我相信乘以一个整数列表是不够好,对吗? '[1,2,3] * 4' – C2H5OH 2012-04-26 00:06:42
@ C2H5OH这将创建列表的4个浅拷贝(N个拷贝是不需要的)。 – Darthfett 2012-04-26 00:17:52
@Darthfett:确实。这就是为什么它是一个评论。但是你会同意这是最优雅的解决方案:-P – C2H5OH 2012-04-26 00:19:22