Search code examples
pythonlistcombinationsproductpython-itertools

want to combine every element of a list with every element of n lists


I'm going to try to explain this with an example, since I seem to have a problem explaining it to myself:

imagine I have a list of strings, and another list of lists of strings:

words = ["hello", "goodbye", "foo"]
lists = [["111", "450", "nice"], ["can", "be", "of", "different", "sizes"]]

I want to combine 1 item of the first list with only 1 item of n lists in lists, example:

For n = 1:

hello111
hello450
hellonice
hellocan
hellobe
...

or n = 2

hello111can
hello111be
hello111of
...

n = 3 would not be possible in this scenario I'm trying this in python with itertools using product or something but I can't seem to wrap my head around how to do this

[EDIT] The answer I marked as correct is what I want but with permutations instead of combinations, Thanks a TON!


Solution

  • from itertools import combinations, product
    
    words = ["hello", "goodbye", "foo"]
    lists = [["111", "450", "nice"], ["can", "be", "of", "different", "sizes"]]
    
    # how many elements of `lists` to pick from?
    for n in range(1, len(lists) + 1):
        # This returns in-order combinations, ie you will get
        # '111', 'can'  and not 'can', '111'.
        # If you want all orderings as well as all combinations,
        # use itertools.permutations instead,
        for sublist in combinations(lists, n):
            # now we generate all combinations of
            # one element from each basis list,
            basis = [words] + list(sublist)
            for combo in product(*basis):
                # and display the result
                print("".join(combo))
    

    which gives

    hello111
    hello450
    hellonice
    goodbye111
    goodbye450
    goodbyenice
    foo111
    foo450
    foonice
    hellocan
    hellobe
    helloof
    hellodifferent
    hellosizes
    goodbyecan
    goodbyebe
    goodbyeof
    goodbyedifferent
    goodbyesizes
    foocan
    foobe
    fooof
    foodifferent
    foosizes
    hello111can
    hello111be
    hello111of
    hello111different
    hello111sizes
    hello450can
    hello450be
    hello450of
    hello450different
    hello450sizes
    hellonicecan
    hellonicebe
    helloniceof
    hellonicedifferent
    hellonicesizes
    goodbye111can
    goodbye111be
    goodbye111of
    goodbye111different
    goodbye111sizes
    goodbye450can
    goodbye450be
    goodbye450of
    goodbye450different
    goodbye450sizes
    goodbyenicecan
    goodbyenicebe
    goodbyeniceof
    goodbyenicedifferent
    goodbyenicesizes
    foo111can
    foo111be
    foo111of
    foo111different
    foo111sizes
    foo450can
    foo450be
    foo450of
    foo450different
    foo450sizes
    foonicecan
    foonicebe
    fooniceof
    foonicedifferent
    foonicesizes
    

    That produces all n=1 before n=2, n=3, etc. If you do not care about the ordering, you could instead do

    for word in words:
        combos = product(*([""] + sublist for sublist in lists))
        next(combos)   # skip n=0
        for combo in combos:
            print(word + "".join(combo))
    

    which produces

    hellocan
    hellobe
    helloof
    hellodifferent
    hellosizes
    hello111
    hello111can
    hello111be
    hello111of
    hello111different
    hello111sizes
    hello450
    hello450can
    hello450be
    hello450of
    hello450different
    hello450sizes
    hellonice
    hellonicecan
    hellonicebe
    helloniceof
    hellonicedifferent
    hellonicesizes
    goodbyecan
    goodbyebe
    goodbyeof
    goodbyedifferent
    goodbyesizes
    goodbye111
    goodbye111can
    goodbye111be
    goodbye111of
    goodbye111different
    goodbye111sizes
    goodbye450
    goodbye450can
    goodbye450be
    goodbye450of
    goodbye450different
    goodbye450sizes
    goodbyenice
    goodbyenicecan
    goodbyenicebe
    goodbyeniceof
    goodbyenicedifferent
    goodbyenicesizes
    foocan
    foobe
    fooof
    foodifferent
    foosizes
    foo111
    foo111can
    foo111be
    foo111of
    foo111different
    foo111sizes
    foo450
    foo450can
    foo450be
    foo450of
    foo450different
    foo450sizes
    foonice
    foonicecan
    foonicebe
    fooniceof
    foonicedifferent
    foonicesizes
    

    (same list, different order).