Jay Gattuso
Jay Gattuso

Reputation: 4130

How to pull all the unique combinations from a list of lists

I want to iterate over a list of lists, and pull all the combinations from the lists.

I can do it in the following way:

list = [['1','2','3'],['a','b','c'],['x','y','z']]
for itemi in list[0]:
    print itemi
    for itemj in list[1]:
        print itemi+itemj
        for itemk in list[2]:
            print itemi+itemj+itemk

My problem is that I want to do it over a varying number of lists in the list o' lists. There will be at first just one list, and (for now) end with 64 lists.

The above example is for 3 lists, and in reality all the lists contain the same values (zero to 255). I used the above examples just so you can see what the output should look like.

I figured there must be a better way to this, without having to build the nested for loops for each size of list of lists.

Upvotes: 2

Views: 916

Answers (1)

Tim Pietzcker
Tim Pietzcker

Reputation: 336258

Use itertools.product():

>>> l = [['1','2','3'],['a','b','c'],['x','y','z']]
>>> import itertools
>>> list(itertools.product(*l))
[('1', 'a', 'x'), ('1', 'a', 'y'), ('1', 'a', 'z'), ('1', 'b', 'x'), 
 ('1', 'b', 'y'), ('1', 'b', 'z'), ('1', 'c', 'x'), ('1', 'c', 'y'), 
 ('1', 'c', 'z'), ('2', 'a', 'x'), ('2', 'a', 'y'), ('2', 'a', 'z'), 
 ('2', 'b', 'x'), ('2', 'b', 'y'), ('2', 'b', 'z'), ('2', 'c', 'x'), 
 ('2', 'c', 'y'), ('2', 'c', 'z'), ('3', 'a', 'x'), ('3', 'a', 'y'), 
 ('3', 'a', 'z'), ('3', 'b', 'x'), ('3', 'b', 'y'), ('3', 'b', 'z'), 
 ('3', 'c', 'x'), ('3', 'c', 'y'), ('3', 'c', 'z')]

This is not quite what you want yet, but it's easy to get there:

>>> for i in range(len(l)):
...     print(list(itertools.product(*l[:i+1])))
...
[('1',), ('2',), ('3',)]
[('1', 'a'), ('1', 'b'), ('1', 'c'), ('2', 'a'), ('2', 'b'), ('2', 'c'), 
 ('3', 'a'), ('3', 'b'), ('3', 'c')]
[('1', 'a', 'x'), ('1', 'a', 'y'), ('1', 'a', 'z'), ('1', 'b', 'x'), 
 ('1', 'b', 'y'), ('1', 'b', 'z'), ('1', 'c', 'x'), ('1', 'c', 'y'), 
 ('1', 'c', 'z'), ('2', 'a', 'x'), ('2', 'a', 'y'), ('2', 'a', 'z'), 
 ('2', 'b', 'x'), ('2', 'b', 'y'), ('2', 'b', 'z'), ('2', 'c', 'x'), 
 ('2', 'c', 'y'), ('2', 'c', 'z'), ('3', 'a', 'x'), ('3', 'a', 'y'), 
 ('3', 'a', 'z'), ('3', 'b', 'x'), ('3', 'b', 'y'), ('3', 'b', 'z'), 
 ('3', 'c', 'x'), ('3', 'c', 'y'), ('3', 'c', 'z')]

Get everything in one list:

>>> result = []
>>> for i in range(len(l)):
...     result.extend(list(itertools.product(*l[:i+1])))
...
>>> result
[('1',), ('2',), ('3',), ('1', 'a'), ('1', 'b'), ('1', 'c'), ('2', 'a'), 
 ('2', 'b'), ('2', 'c'), ('3', 'a'), ('3', 'b'), ('3', 'c'), ('1', 'a', 'x'), 
 ('1', 'a', 'y'), ('1', 'a', 'z'), ('1', 'b', 'x'), ('1', 'b', 'y'), 
 ('1', 'b', 'z'), ('1', 'c', 'x'), ('1', 'c', 'y'), ('1', 'c', 'z'), 
 ('2', 'a', 'x'), ('2', 'a', 'y'), ('2', 'a', 'z'), ('2', 'b', 'x'), 
 ('2', 'b', 'y'), ('2', 'b', 'z'), ('2', 'c', 'x'), ('2', 'c', 'y'), 
 ('2', 'c', 'z'), ('3', 'a', 'x'), ('3', 'a', 'y'), ('3', 'a', 'z'), 
 ('3', 'b', 'x'), ('3', 'b', 'y'), ('3', 'b', 'z'), ('3', 'c', 'x'), 
 ('3', 'c', 'y'), ('3', 'c', 'z')]

Get it in the exact shape you want:

>>> sorted(result)
[('1',), ('1', 'a'), ('1', 'a', 'x'), ('1', 'a', 'y'), ('1', 'a', 'z'), 
 ('1', 'b'), ('1', 'b', 'x'), ('1', 'b', 'y'), ('1', 'b', 'z'), ('1', 'c'), 
 ('1', 'c', 'x'), ('1', 'c', 'y'), ('1', 'c', 'z'), ('2',), ('2', 'a'), 
 ('2', 'a', 'x'), ('2', 'a', 'y'), ('2', 'a', 'z'), ('2', 'b'), ('2', 'b', 'x'), 
 ('2', 'b', 'y'), ('2', 'b', 'z'), ('2', 'c'), ('2', 'c', 'x'), ('2', 'c', 'y'), 
 ('2', 'c', 'z'), ('3',), ('3', 'a'), ('3', 'a', 'x'), ('3', 'a', 'y'), 
 ('3', 'a', 'z'), ('3', 'b'), ('3', 'b', 'x'), ('3', 'b', 'y'), ('3', 'b', 'z'), 
 ('3', 'c'), ('3', 'c', 'x'), ('3', 'c', 'y'), ('3', 'c', 'z')]

Upvotes: 11

Related Questions