13

我想通过迭代器重复(N次)循环遍历列表,以免实际将列表的N个副本存储在内存中。有没有内置的或优雅的方法可以在不编写我自己的生成器的情况下做到这一点?

理想情况下, itertools.cycle(my_list) 会有第二个参数来限制它循环的次数......唉,没有这样的运气。

4

6 回答 6

21
import itertools
itertools.chain.from_iterable(itertools.repeat([1, 2, 3], 5))

Itertools 是一个很棒的库。:)

于 2012-04-26T00:08:35.440 回答
12

所有其他答案都很好。另一种解决方案是使用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]
于 2012-04-26T00:26:30.267 回答
8
itertools.chain.from_iterable(iter(L) for x in range(N))
于 2012-04-26T00:07:23.660 回答
6

对于需要多次迭代列表的特殊情况,这还不错。

它确实创建了一个n引用列表my_list,所以如果n非常大,最好使用 Darthfelt 的答案

>>> import itertools as it
>>> it.chain(*[my_list]*n)
于 2012-04-26T00:14:06.613 回答
5

您说您不想编写自己的生成器,但是生成器表达式可能是完成您所追求的最简单和最有效的方法。它不需要任何函数调用或任何模块的导入。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)
于 2012-04-26T01:36:25.967 回答
4

@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']
于 2017-08-22T20:55:11.870 回答