Esser420
Esser420

Reputation: 860

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!

Upvotes: 3

Views: 2034

Answers (2)

Hugh Bothwell
Hugh Bothwell

Reputation: 56654

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).

Upvotes: 1

tobias_k
tobias_k

Reputation: 82899

First, get the combinations of n elements from lists using itertools.combinations(lists, n), then get the product of the original words and the elements from that combination using itertools.product(words, *comb). You can combine both steps into one double-loop list comprehension:

>>> n = 1
>>> [x for comb in itertools.combinations(lists, n) for x in itertools.product(words, *comb)]
[('hello', '111'),
 ('hello', '450'),
 ('hello', 'nice'),
 ('goodbye', '111'),
 ...
 ('foo', 'sizes')]

Or for n = 2:

[('hello', '111', 'can'),
 ('hello', '111', 'be'),
 ('hello', '111', 'of'),
 ('hello', '111', 'different'),
 ('hello', '111', 'sizes'),
 ('hello', '450', 'can'),
 ...
 ('foo', 'nice', 'sizes')]

And for n = 3 and above you get [].

Finally, just ''.join those together. (I did not so it's more readable.)

>>> [''.join(x) for comb in itertools.combinations(lists, n) for x in itertools.product(words, *comb)]

Upvotes: 1

Related Questions