[英]Itertools instead of nested loops
list_a = []
for color in [True,False]:
for piece in range(1,7):
list_a = list_a + function(piece,color)
Here the function(piece,color)
returns a list, which I want to join and finally return the long list, can itertools.chain
be used here? 在这里,
function(piece,color)
返回一个列表,我想加入该列表并最终返回长列表,在这里可以使用itertools.chain
吗? because I think it might be faster. 因为我认为它可能会更快。 I am only displaying an example, but in my actual code the loop runs about 100,000 times, which is why I am looking for a faster method.
我仅显示一个示例,但是在我的实际代码中,循环运行了大约100,000次,这就是为什么我在寻找更快的方法。
I'm going to answer the question you should have asked instead ;-) 我将回答您应该问的问题;-)
This: 这个:
list_a = list_a + function(piece,color)
takes time quadratic in the number of times it's executed. 花费的时间是执行次数的二次方。 Each time, a brand new list object is created, copying the entirety of the old
list_a
and the new list. 每次创建一个全新的列表对象时,将复制整个旧
list_a
和新列表。
So if it's executed many times, you can get a huge improvement by changing it to this: 因此,如果它多次执行,则可以通过将其更改为以下内容来获得巨大的改进:
list_a.extend(function(piece,color))
Then list_a
is extended "in place" whenever possible; 然后,在可能的情况下将
list_a
扩展为“就位”; under the covers, it may need to make a copy to a larger memory area from time to time, but overall the amortized time is linear in the number of times it's executed. 在幕后,它可能需要不时地复制到更大的存储区域,但是总的来说,摊销的时间在执行的次数上是线性的。
If you really want to use itertools.chain
: 如果您真的想使用
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))))
Of course, if you use list_a += function(piece, color)
this would likely be just as fast (maybe faster?). 当然,如果使用
list_a += function(piece, color)
,则速度可能会一样快(也许更快?)。
The problem with list_a = list_a + function(piece, color)
is that this line is quadratic in it's input, because it builds an entirely new list, whereas list_a += function(piece, color)
is the equivalent of using extend
, which for Python lists is amortized constant time, so the inner part stays linear instead of quadratic. list_a = list_a + function(piece, color)
的问题在于该行在输入中是二次方的,因为它建立了一个全新的列表,而list_a += function(piece, color)
相当于使用extend
,对于Python列表是摊销的固定时间,因此内部部分保持线性而不是二次线性。
yield from
seems to be the simple solution here. yield from
似乎是这里的简单解决方案。
def generator():
for color in [True,False]:
for piece in range(1,7):
yield from function(piece,color)
You can use itertools.starmap
, although you'll still have the loops, you can't really escape from them: 您可以使用
itertools.starmap
,尽管仍然有循环,但您无法真正摆脱循环:
result_generator = starmap(function, ((piece, color) for piece in range(1,7) for color in [True,False]))
list_a = list(result_generator)
Then, use itertools.product
like this: 然后,像这样使用
itertools.product
:
result_generator = starmap(function, product(range(1,7), [True,False]))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.