Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Combinations of multiple lists

Tags:

python

Suppose I have three lists:

list1 --> [a, b, c, d, e, f, g, h]
list2 --> [i, j, k]
list3 --> [l, m, n, o, p]

I wish to generate all combinations where I take five elements from list1, two elements from list2 and three elements from list3.

eg.

a, b, c, d, e, i, j, l, m, n  
a, b, c, d, e, i, j, l, m, o
etc.

I tried to use itertools.combinations.

l1_combinations = itertools.combinations(list1, 5)
l2_combinations = itertools.combinations(list2, 2)
l3_combinations = itertools.combinations(list3, 3)
for l1_iterator in list(l1_combinations):
    for l2_iterator in list(l2_combinations): #added a missing )
        for l3_iterator in list(l3_combinations):
            sample = l1_iterator + l2_iterator + l3_iterator
            print(sample)

But I am getting output with iterations happening only on list3. In all the output, only first five elements from list1 and first two elements from list2 are present. Combinations with other elements from those two lists aren't present.

Can someone help me here and also explain what exactly did i miss ?

like image 457
Arun Aranganathan Avatar asked Apr 04 '19 19:04

Arun Aranganathan


2 Answers

As an alternative to regenerating the list of combinations, compute the product of the combinations up front; this also saves you from nesting for loops.

from itertools import combinations, product


list1 = list("abcdefgh")
list2 = list("ijk")
list3 = list("lmnop")

l1 = combinations(list1, 5)
l2 = combinations(list2, 2)
l3 = combinations(list3, 3)
for c1, c2, c3 in product(l1, l2, l3):
    sample = c1 + c2 + c3
    print(sample)
like image 110
chepner Avatar answered Oct 23 '22 02:10

chepner


Don't iterate over the same iterator multiple times, after the first time it's exhausted. Iterate over a fresh iterator each time:

for l1_iterator in itertools.combinations(list1, 5):
    for l2_iterator in itertools.combinations(list2, 2):
        for l3_iterator in itertools.combinations(list3, 3):
            sample = l1_iterator + l2_iterator + l3_iterator
            print(sample)

Or make lists of each one in advance to avoid recomputation:

l1_combinations = list(itertools.combinations(list1, 5))
l2_combinations = list(itertools.combinations(list2, 2))
l3_combinations = list(itertools.combinations(list3, 3))
for l1_iterator in l1_combinations:
    for l2_iterator in l2_combinations:
        for l3_iterator in l3_combinations:
            sample = l1_iterator + l2_iterator + l3_iterator
            print(sample)
like image 41
Alex Hall Avatar answered Oct 23 '22 02:10

Alex Hall