Avoiding nested for loops

Question:

I am trying to test some other Python code repeatedly, using all possible combinations of values for six different parameters. For each parameter I want to iterate over a range of values with a given minimum, maximum and step.

I managed to write some code like:

for var1 in range(min1, max1, step1):
    for var2 in range(min2, max2, step2):
        for var3 in range(min3, max3, step3):
            for var4 in range(min4, max4, step4):
                for var5 in range(min5, max5, step5):
                    for var6 in range(min6, max6, step6):
                        do_something_with(var1, var2, var3, var4, var5, var6)

But I do not like that the code is so deeply nested.

How can I avoid nesting multiple loops? Can it be done using recursion? How about itertools.product? I wasn’t able to figure out either approach.


See also, more generally: Get the cartesian product of a series of lists?

This question, and some answers, originally showed code for Python 2.x. It has been edited because the fundamental problem persists in 3.x, with the same solution, but xrange no longer exists – range is the drop-in replacement. For more information, see What is the difference between range and xrange functions in Python 2.X?.

Asked By: rapidsnow

||

Answers:

You can probably use itertools.product. Something like

for var1, var2 in itertools.product(range(min1, max1, step1), range(min2, max2, step2)):
    # stuff

but with all six vars in there.

Answered By: BrenBarn

Here’s how to use product:

x1 = range(min1, max1, step1)
x2 = range(min2, max2, step2)
x3 = range(min3, max3, step3)
...

for v1, v2, v3, v4, v5, v6 in itertools.product(x1, x2, x3, x4, x5, x6):
    do_something_with(v1, v2, v3, v4, v5, v6)

or a bit more compactly:

ranges = [
    range(min1, max1, step1),
    range(min2, max2, step2),
    range(min3, max3, step3),
    ...
]

for v1, v2, v3, v4, v5, v6 in itertools.product(*ranges):
    do_something_with(v1, v2, v3, v4, v5, v6)
Answered By: Ned Batchelder

you can use multiprocessing and itertools.product to speed up and simplify your code

import itertools
from multiprocessing import Pool

ranges = [
    range(min1,max1,step1),
    range(min2,max2,step2),
    range(min3,max3,step3),
    ...
]

with Pool(os.cpu_count()-2) as p:
    result = p.map(your_op_func, itertools.product(*ranges))
  1. multiprocessing can speed up your task (because it’s mutex task)
  2. itertools.product can help you get combinations through a more effectively way
Answered By: zhangjq
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.