1

I'm reposting this question because I was told that there is a solution for that in the last post.

I have 2 lists:

list1 = ["foo", "bar", "lorem"]
list2 = ["X", "Y"]

I want to have the possible combinations from these 2 lists, meaning:

[["foo", "bar", "lorem"],
 ["foo", "bar", "loremX"],
 ["foo", "barX", "loremX"],
 ["fooX", "bar", "loremX"],
 ["fooX", "barX", "loremX"],
 ["foo", "barX", "lorem"],
 ["fooX", "barX", "lorem"],
 ["fooX", "bar", "lorem"],

 ["foo", "bar", "lorem"],
 ["foo", "bar", "loremY"],
 ["foo", "barY", "loremY"],
 ["fooY", "bar", "loremY"],
 ["fooY", "barY", "loremY"],
 ["foo", "barY", "lorem"],
 ["fooY", "barY", "lorem"],
 ["fooY", "bar", "lorem"]]

Hope I didn't miss any combination.

Kinda lost with this one.

It probably should be something with itertools.combinations_with_replacement

Thanks.

EDIT

First of all, thanks to @titusarmah99 for a great answer. I managed to take his second-and-very-simple solution and make it generic:

import itertools

list1 = ["foo", "bar", "lorem"]
list2 = ["X", "Y"]
list2new = [""] + list2
newList = [[list1[i]+list2new[j] for j in range(len(list2new))] for i in range(len(list1))]

for index in range(1, len(list2) + 1):
    for c in itertools.product([0,index],repeat=len(list1)):
        tmp = [newList[i][c[i]] for i in range(len(c))]
        print(tmp)

  • I think, the final result you are showing doesn't quite match with the definition of all possible combinations. Would you explain what you want to find? – impopularGuy May 05 '20 at 03:46
  • @titusarmah99 You're right, I just noticed that. I want to find all the combinations of value in list1 + value in list2 bu not value in list2+value in list1. – Mr. Someone May 05 '20 at 03:48
  • what about combinations like `['fooX', 'bar', 'loremX']` , `['fooX', 'barX', 'loremY']` or `['fooX', 'barY', 'lorem']` ? – impopularGuy May 05 '20 at 03:56
  • @titusarmah99 If you have a solution without them, it would be great. Otherwise, I will be able to handle them. – Mr. Someone May 05 '20 at 03:58

2 Answers2

0

The key here is to use rotation. There are many ways to rotate an array, i will be using deque.

from collections import deque

list1 = ["foo", "bar", "lorem"]
list2 = ["X", "Y"]
list2new = [""] + list2
print(list2new) # ['', 'X', 'Y']

newList = [[list1[i]+list2new[j] for j in range(len(list2new))] for i in range(len(list1))]
print(newList)
# [['foo', 'fooX', 'fooY'], ['bar', 'barX', 'barY'], ['lorem', 'loremX', 'loremY']]

d = deque([0,0,0,1,1,1])
for it in range(2*len(list1)):
    tmp = [newList[i][d[i]] for i in range(len(list1))]
    print(tmp) #
    d.rotate(1)
# ['foo', 'bar', 'lorem']
# ['fooX', 'bar', 'lorem']
# ['fooX', 'barX', 'lorem']
# ['fooX', 'barX', 'loremX']
# ['foo', 'barX', 'loremX']
# ['foo', 'bar', 'loremX']

After this we can repeat the process for rest of values in list2.

for x in range(1,len(list2new)):
    d = deque([0]*len(list1)+[x]*len(list1))
    d.rotate(1)
    for it in range(2*len(list1)-1): #
        tmp = [newList[i][d[i]] for i in range(len(list1))]
        print(tmp) #
        d.rotate(1)
# ['fooX', 'bar', 'lorem']
# ['fooX', 'barX', 'lorem']
# ['fooX', 'barX', 'loremX']
# ['foo', 'barX', 'loremX']
# ['foo', 'bar', 'loremX']
# ['fooY', 'bar', 'lorem']
# ['fooY', 'barY', 'lorem']
# ['fooY', 'barY', 'loremY']
# ['foo', 'barY', 'loremY']
# ['foo', 'bar', 'loremY']

This will not contain ['foo', 'bar', 'lorem'] so add it manually.

EDIT: Seems, like you edited the question. To get all possible combinations, just use newList and itertools.product

for c in itertools.product([0,1],repeat=3):
    tmp = [newList[i][c[i]] for i in range(len(c))]
    print(tmp) #
impopularGuy
  • 805
  • 9
  • 15
  • Yeah, I wanted to add the rest of the combinations I missed. Testing your solution now, looks great so far! – Mr. Someone May 05 '20 at 04:50
  • The first solution you gave works like magic! The second one gives me only the first part (only for "X"). I think I'll go with the first one. Thank you very much! – Mr. Someone May 05 '20 at 04:56
  • For the second part to work for 'Y' also, you will need to repeat it again i.e. in `itertools.product([0,1],repeat=3)` replace `[0,1]` with `[0,2]`. You can use another for loop for do this programatically – impopularGuy May 05 '20 at 05:00
0

Combine each string in list2 with the empty string, then zip the result with list1 and join the strings.

from itertools import product

for item in list2:
    for suffixes in product(['', item], repeat=3):
        print([x + s for x, s in zip(list1, suffixes)])

Output:

['foo', 'bar', 'lorem']
['foo', 'bar', 'loremX']
['foo', 'barX', 'lorem']
['foo', 'barX', 'loremX']
['fooX', 'bar', 'lorem']
['fooX', 'bar', 'loremX']
['fooX', 'barX', 'lorem']
['fooX', 'barX', 'loremX']
['foo', 'bar', 'lorem']
['foo', 'bar', 'loremY']
['foo', 'barY', 'lorem']
['foo', 'barY', 'loremY']
['fooY', 'bar', 'lorem']
['fooY', 'bar', 'loremY']
['fooY', 'barY', 'lorem']
['fooY', 'barY', 'loremY']

Here I'm printing to show the lists on one line each, but you could easily modify this to append them to another list.

wjandrea
  • 28,235
  • 9
  • 60
  • 81