'Avoiding nested for loops
I am trying to do some parameter testing on another code using python. I need to test 6 independent parameters, but I need all of the possible combinations of them.
Each parameter has a minimum, a maximum, and a step value that needs to be passed to it. The first easy solution that popped into my head was a nested for loop structure that looked horrific, like this:
for var1 in xrange(min1,max1,step1):
for var2 in xrange(min2,max2,step2):
...
...
...
for var6 in xrange(min6,max6,step6):
'''
Do something and be icky in the process due
to being in the middle of six nested for loops
'''
I decided, no! This shall not stand. So I've been trying to work out a way to do this recursively, or at the very least, not nested six times. I can't really come up with a good scheme to do so. The biggest obstacle for me is that each variable has a different min, max, and step value.
My thoughts so far aren't very helpful. I keep trying to make some recursive function work, but I just can't figure it out without nesting more for loops within the function. I've seen a lot of reference to itertools.product on here, but I can't quite figure out how to make that work either.
Edit: What I'm doing is creating a directory named after the combination of the parameters, writing a file with those parameters, running another code with this file, and analyzing the output from that code. I am doing nothing in literally any of the for loops except for the final one. A lot of the parameters only have 2 values, some have 10, others have 3... it just kind of varies.
Solution 1:[1]
Here's how to use product
:
x1 = xrange(min1,max1,step1)
x2 = xrange(min2,max2,step2)
x3 = xrange(min3,max3,step3)
...
for v1, v2, v3, v4, v5, v6 in itertools.product(x1, x2, x3, x4, x5, x6):
icky_thing(....)
or a bit more compactly:
ranges = [
xrange(min1,max1,step1),
xrange(min2,max2,step2),
xrange(min3,max3,step3),
...
]
for v1, v2, v3, v4, v5, v6 in itertools.product(*ranges):
icky_thing(....)
Solution 2:[2]
You can probably use itertools.product
: http://docs.python.org/library/itertools.html#itertools.product .
Something like
for var1, var2 in itertools.product(xrange(min1, max1, step1), xrange(min2, max2, step2)):
# stuff
. . . only with all six vars in there.
Solution 3:[3]
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))
multiprocessing
can speed up your task (because it's mutex task)itertools.product
can help you get combinations through a more effectively way
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Ned Batchelder |
Solution 2 | BrenBarn |
Solution 3 | DharmanBot |