Creating unique combinations from lists

Tim Chase python.list at tim.thechases.com
Wed Jan 16 15:40:07 EST 2008


> 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





More information about the Python-list mailing list