简体   繁体   English

Itertools而不是嵌套循环

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM