我想通过迭代器重复(N次)地循环遍历列表,而不是实际上在内存中存储N个列表副本。是否有内置或优雅的方法可以做到这一点,而无需编写自己的生成器?
理想情况下,itertools.cycle(my_list)会有第二个参数来限制它循环的次数......但遗憾的是,并没有这样的运气。
理想情况下,itertools.cycle(my_list)会有第二个参数来限制它循环的次数......但遗憾的是,并没有这样的运气。
import itertools
it = itertools.chain.from_iterable(itertools.repeat([1, 2, 3], 5))
print(list(it))
# [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
Itertools 是一个很棒的库。 :)
正如评论中指出的那样,如果您正在使用迭代器(而不是列表或类似的集合),则在第一次迭代后迭代器会被耗尽,因此您需要使用稍微不同的方法来获得预期的结果。请注意,无限或过长的迭代器无法合理处理,因为您将不得不缓存结果(需要无限或过多的内存)。
这可能不是最有效的实现方式(tee
存储 iterable 的内容的 N 个副本):
import itertools
it = itertools.chain(*itertools.tee(iter([1, 2, 3]), 5))
print(list(it))
# [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
repeat
的第一个参数是可消耗的迭代器,则此方法将无法正常工作。例如,list(itertools.chain.from_iterable(itertools.repeat(iter([1, 2, 3]), 2)))
的结果为[1, 2, 3]
,而不是[1, 2, 3, 1, 2, 3]
。这是因为迭代器在第一次迭代时就被消耗完了。 - user2846495itertools.tee
创建可迭代对象的副本,这将使得使用 list(itertools.chain(*itertools.tee(iter([1, 2, 3]), 5)))
实现变得相当简单。 - Casey Kuballitertools.tee
来创建可迭代对象的副本,这样就可以很简单地实现了。例如,可以使用list(itertools.chain(*itertools.tee(iter([1, 2, 3]), 5)))
来实现。 - Casey Kuball其他的答案都很好。另一个解决方案是使用 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]
cycle
返回的可迭代对象是无限长的。 - senderleitertools.chain.from_iterable(iter(L) for x in range(N))
如果需要多次遍历列表,则这并不太麻烦。它会创建一个包含n个对my_list的引用的列表,所以如果n非常大,则最好使用Darthfelt的答案。
>>> import itertools as it
>>> it.chain(*[my_list]*n)
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的答案记录在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