2017-04-10 219 views
1
list_a = [] 
for color in [True,False]: 
    for piece in range(1,7): 
     list_a = list_a + function(piece,color) 

這裏function(piece,color)返回一個列表,我想加入,最後返回長長的名單,可以itertools.chain在這裏使用?因爲我認爲它可能會更快。我只顯示一個例子,但在我的實際代碼循環運行約10萬次,這就是爲什麼我正在尋找一個更快的方法。Itertools代替嵌套循環

回答

5

我會回答你應該問,而不是問題;-)

此:

list_a = list_a + function(piece,color) 

需要時間二次在它執行的次數。每次都會創建一個全新的列表對象,並複製整個舊的list_a和新列表。

所以,如果它多次執行,您可以通過它來改變這得到了巨大的改善:

list_a.extend(function(piece,color)) 

然後list_a是「到位」只要有可能延長;在其覆蓋範圍內,可能會不時需要複製到更大的內存區域,但總體而言,分攤時間與執行次數成線性關係。

+0

最好的種類的答案解釋瞭如何解決它以及爲什麼他們錯了。其他人都沒有解釋爲什麼'lst = lst + ele'是一個壞主意。 – TemporalWolf

1

yield from似乎是這裏的簡單解決方案。

def generator(): 
    for color in [True,False]: 
     for piece in range(1,7): 
      yield from function(piece,color) 
2

如果你真的使用itertools.chain:(?也許更快)

>>> from itertools import product, chain 
>>> list_a = list(chain.from_iterable(function(piece, color) for piece, color in product([True, False], range(1, 7)))) 

當然,如果你使用list_a += function(piece, color)這很可能是一樣快。

list_a = list_a + function(piece, color)的問題是,這條線是二次在它的輸入端,因爲它建立了一個全新的列表,而list_a += function(piece, color)是使用extend,這對於Python列表攤銷恆定時間的相等的,所以內部部分保持線性而不是二次方。

0

您可以使用itertools.starmap,但你仍然有循環,你真的不能從他們逃脫:

result_generator = starmap(function, ((piece, color) for piece in range(1,7) for color in [True,False])) 

list_a = list(result_generator) 

然後,使用itertools.product這樣的:

result_generator = starmap(function, product(range(1,7), [True,False]))