Search code examples
pythoncombinationspermutationpython-itertools

How find all combinations of two lists with python itertools, repeating one list but not the other


I have two lists, listA and listB. List C would be every value of list A paired with a value from list B (list B items can be repeated). I would like to find every possible combination of list C

listA = [1, 2, 3, 4, 5]
listB = ['a', 'b', 'c']
import itertools

listA = [1, 2, 3, 4, 5]
listB = ['a', 'b', 'c']

for item in itertools.permutations(x for x in itertools.product(listA,listB)):
    print(item)

Yields many lists like this:

((1, 'a'), (1, 'b'), (1, 'c'), (2, 'a'), (2, 'b'), (2, 'c'), (3, 'a'), (3, 'b'), (3, 'c'), (4, 'a'), (4, 'b'), (4, 'c'), (5, 'a'), (5, 'b'), (5, 'c')) 

What I would like it to yield is lists where items in listA are not repeated, like this:

((1, 'a'),  (2, 'a'),  (3, 'a'),  (4, 'a'), (5, 'a')),((1, 'b'),  (2, 'a'),  (3, 'a'),  (4, 'a'), (5, 'a')),((1, 'b'),  (2, 'b'),  (3, 'a'),  (4, 'a'), (5, 'a'))...

progressing further:

((1, 'b'),  (2, 'b'),  (3, 'b'),  (4, 'b'), (5, 'b')),((1, 'c'),  (2, 'b'),  (3, 'b'),  (4, 'b'), (5, 'b')),((1, 'c'),  (2, 'c'),  (3, 'b'),  (4, 'b'), (5, 'b')),

Extended desired output:

((1, 'a'),  (2, 'a'),  (3, 'a'),  (4, 'a'), (5, 'a')),
((1, 'b'),  (2, 'a'),  (3, 'a'),  (4, 'a'), (5, 'a')),
((1, 'b'),  (2, 'b'),  (3, 'a'),  (4, 'a'), (5, 'a')),
((1, 'b'),  (2, 'b'),  (3, 'b'),  (4, 'a'), (5, 'a')),
((1, 'b'),  (2, 'b'),  (3, 'b'),  (4, 'b'), (5, 'a')),
((1, 'b'),  (2, 'b'),  (3, 'b'),  (4, 'b'), (5, 'b')),
((1, 'c'),  (2, 'b'),  (3, 'b'),  (4, 'b'), (5, 'b')),
((1, 'c'),  (2, 'c'),  (3, 'b'),  (4, 'b'), (5, 'b')),
...
((1, 'c'),  (2, 'c'),  (3, 'c'),  (4, 'c'), (5, 'c')),
((1, 'a'),  (2, 'c'),  (3, 'c'),  (4, 'c'), (5, 'c')),
((1, 'a'),  (2, 'a'),  (3, 'c'),  (4, 'c'), (5, 'c')),
((1, 'a'),  (2, 'a'),  (3, 'a'),  (4, 'c'), (5, 'c')),
...
((1, 'a'),  (2, 'b'),  (3, 'c'),  (4, 'c'), (5, 'c')),
...
((1, 'a'),  (2, 'a'),  (3, 'c'),  (4, 'c'), (5, 'c')),
...
((1, 'c'),  (2, 'c'),  (3, 'c'),  (4, 'c'), (5, 'a')),
...

Solution

  • You could zip listA with each combination produced by the product function on listB with as many repeats as the size of listA:

    listA = [1, 2, 3, 4, 5]
    listB = ['a', 'b', 'c']
    
    from itertools import product
    
    listC = ( tuple(zip(listA,combo))
              for combo in product(listB,repeat=len(listA)))
    
    for c in listC: print(c)
    
        
    ((1, 'a'), (2, 'a'), (3, 'a'), (4, 'a'), (5, 'a'))
    ((1, 'a'), (2, 'a'), (3, 'a'), (4, 'a'), (5, 'b'))
    ((1, 'a'), (2, 'a'), (3, 'a'), (4, 'a'), (5, 'c'))
    ((1, 'a'), (2, 'a'), (3, 'a'), (4, 'b'), (5, 'a'))
    ((1, 'a'), (2, 'a'), (3, 'a'), (4, 'b'), (5, 'b'))
    ((1, 'a'), (2, 'a'), (3, 'a'), (4, 'b'), (5, 'c'))
    ((1, 'a'), (2, 'a'), (3, 'a'), (4, 'c'), (5, 'a'))
    ((1, 'a'), (2, 'a'), (3, 'a'), (4, 'c'), (5, 'b'))
    ((1, 'a'), (2, 'a'), (3, 'a'), (4, 'c'), (5, 'c'))
    ((1, 'a'), (2, 'a'), (3, 'b'), (4, 'a'), (5, 'a'))
    ...
    ((1, 'c'), (2, 'c'), (3, 'c'), (4, 'a'), (5, 'a'))
    ((1, 'c'), (2, 'c'), (3, 'c'), (4, 'a'), (5, 'b'))
    ((1, 'c'), (2, 'c'), (3, 'c'), (4, 'a'), (5, 'c'))
    ((1, 'c'), (2, 'c'), (3, 'c'), (4, 'b'), (5, 'a'))
    ((1, 'c'), (2, 'c'), (3, 'c'), (4, 'b'), (5, 'b'))
    ((1, 'c'), (2, 'c'), (3, 'c'), (4, 'b'), (5, 'c'))
    ((1, 'c'), (2, 'c'), (3, 'c'), (4, 'c'), (5, 'a'))
    ((1, 'c'), (2, 'c'), (3, 'c'), (4, 'c'), (5, 'b'))
    ((1, 'c'), (2, 'c'), (3, 'c'), (4, 'c'), (5, 'c'))