Tim Chase
1/16/2008 8:40:00 PM
> a = ['big', 'small', 'medium'];
> b = ['old', 'new'];
> c = ['blue', 'green'];
>
> I want to take those and end up with all of the combinations they
> create like the following lists
> ['big', 'old', 'blue']
> ['small', 'old', 'blue']
> ['medium', 'old', 'blue']
> ['big', 'old', 'green']
> ['small', 'old', 'green']
> ['medium', 'small', 'green']
> ['big', 'new', 'blue']
> ['small', 'new', 'blue']
> ['medium', 'new', 'blue']
> ['big', 'new', 'green']
> ['small', 'new', 'green']
> ['medium', 'new', 'green' ]
>
> I could do nested for ... in loops, but was looking for a Pythonic way
> to do this. Ideas?
You can use a recursive generator:
def iterall(*iterables):
if iterables:
for head in iterables[0]:
for remainder in iterall(*iterables[1:]):
yield [head] + remainder
else:
yield []
for thing in iterall(
['big', 'medium', 'small'],
['old', 'new'],
['blue', 'green'],
):
print thing
The two for-loops plus recursion should handle any number of
parameters, so if you were so inclined, you could do
for thing in iterall(
['big', 'medium', 'small'],
['old', 'new'],
['blue', 'green'],
['smelly', 'fragrant'],
['spatula', 'avocado'],
):
print thing
and get all 3*2*2*2*2 items. Or count in binary:
for i, bitstream in enumerate(iterall(
[0, 1],
[0, 1],
[0, 1],
[0, 1],
[0, 1],
[0, 1],
)):
print ''.join(map(str, bitstream)), '=', i
When you're iterating over combinations of items in groups of
lists, I prefer the clarity of this over something like
[(a,b,c,d,e) for a in [0,1] for b in [0,1] for c in [0,1] for
d in [0,1] for e in [0,1]]
-tkc