2017-04-10 109 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]))