2012-04-26 22 views
11

我想通過一個迭代器反覆遍歷一個列表(N次),以免在列表中實際存儲N個列表副本。有沒有內置或優雅的方式來做到這一點,而不寫我自己的發電機?是否有一種優雅的方式通過迭代遍歷列表N次(如itertools.cycle但限制循環)?

理想情況下,itertools.cycle(my_list)將有第二個參數來限制它循環的次數...唉,沒有這樣的運氣。

+0

我相信乘以一個整數列表是不夠好,對嗎? '[1,2,3] * 4' – C2H5OH 2012-04-26 00:06:42

+0

@ C2H5OH這將創建列表的4個淺拷貝(N個拷貝是不需要的)。 – Darthfett 2012-04-26 00:17:52

+0

@Darthfett:確實。這就是爲什麼它是一個評論。但是你會同意這是最優雅的解決方案:-P – C2H5OH 2012-04-26 00:19:22

回答

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

Itertools是一個奇妙的圖書館。 :)

+0

這是一個相當明確的答案,不涉及我自己的生成器/迭代器(儘管馬特安德森的回答顯示這不是太混亂),並且是一個滿足我的問題的第一個答案。所以,我接受它。謝謝!! – JJC 2012-04-26 08:57:02

7
itertools.chain.from_iterable(iter(L) for x in range(N)) 
6

對於需要多次迭代列表的特殊情況,這並不算太壞。

它確實創造n引用列表來my_list,所以如果n是非常大的,最好是用Darthfelt的回答

>>> import itertools as it 
>>> it.chain(*[my_list]*n) 
+0

我試圖避免在內存中複製列表(或引用它),否則只是:mylist * n將會是足夠的。 :-)儘管如此,感謝您的意見。只需要清楚,通過* list運算符擴展列表並將其乘以n而不是將列表乘以n?是否有區別? – JJC 2012-04-26 13:34:52

+0

@JJC,'mylist * n'用'len(mylist)* n)'元素創建一個列表。對於這個答案,你只需創建一個'n'元素列表,所以根據'len(mylist)'和'n',這可能會產生巨大的差異 – 2012-04-26 22:08:05

+0

我明白[1,2,3,4] * 2會創建一個8個元素的列表。那麼,你說* [1,2,3,4] * 2只創建了兩個元素?對不起,我很困惑。謝謝。 – JJC 2012-04-28 09:36:19

5

其他所有的答案都非常優秀。另一種解決方案是使用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] 
+0

不錯,我不知道islice處理大於可迭代長度的「stop」值。 – Darthfett 2012-04-26 00:33:21

+1

@Darthfett,是的,它的確如此。但這在這裏不重要。由'cycle'返回的iterable無限長。 – senderle 2012-04-26 00:35:15

3

你說你不想寫自己的發電機,但發電機表達式很可能會完成你」最簡單,最有效的方法重新過後。它不需要任何函數調用或任何模塊的導入。 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) 
+0

我喜歡這些生成器表達式。它們比我意識到它們適合這種模式更緊湊。我將答案歸功於@Darthfett,因爲技術上我要求一個非自動滾動的發電機,但是如果我可以接受兩個發電機,我也會接受你的(也可能是別人的:-))謝謝! – JJC 2012-04-26 08:52:50

1

@ 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'] 
+0

謝謝,但這與Darthfett接受的答案相同。 – JJC 2017-08-23 13:08:51

+0

是的,它們是等價的。我編輯澄清他的代碼是現有的'itertools'配方(不早於Python 2.3)。我發佈此選項來演示實現這些配方的第三方庫,並在需要時避免手動實施。謝謝。 – pylang 2017-08-23 15:46:29

+1

很酷。 more_itertools包看起來非常方便。感謝分享它。 – JJC 2017-08-24 14:23:59