Home > Blockchain >  Getting combinations for content of x lists in Python
Getting combinations for content of x lists in Python

Time:10-04

My head is about to explode.

I have x lists that each has y length, like this:

    list1 = ["text11","text12", "text13"]
    list2 = ["text21","text22", "text23"]
    list3 = ["text31","text32"]

I'm trying to get a list containing string concatenations of all the "combinations" of the content from each list, seperating them with a " ":

    listFinal = ["text11   text21   text31",
                 "text11   text21   text32",
                 "text11   text22   text31",
                 "text11   text22   text32",
                 "text11   text23   text31",
                 "text11   text23   text32",
                 ...
                 "text13   text23   text32",

I can make it work if the length and the number of the lists are constant using nested loops, but as the lists might vary in quantity and length, i cannot for the love of god figure out how to do this.

Among a lot of things, I have tried making a list containing my lists and then using nested loops where i try to perform the action for the length of the big list. This gives me only "pairwise" combinations.

list = [list1, list2, list3]
for l in range(len(list)):
    for li in list[l]:
        for lii in list[l 1]:
            print("li",li,"lii",lii)

This is super hard for me to explain, but I hope it makes somewhat sense.

Any suggestions on how i can make it output my final list with varying sizes and length of the sublists? Thank you in advance

CodePudding user response:

You can use itertools.product and add ' ' between elements that gets from product like below.

Try this:

import itertools

list1 = ["text11","text12", "text13"]
list2 = ["text21","text22", "text23"]
list3 = ["text31","text32"]
list4 = ["text41","text42","text43"]
list5 = ["text51","text52","text53"]

lists = [list1]   [list2]   [list3]   [list4]   [list5]

final_list = [' '.join(pr) for pr in (itertools.product(*lists))]

Output:

>>> final_list

['text11 text21 text31 text41 text51',
 'text11 text21 text31 text41 text52',
 'text11 text21 text31 text41 text53',
 'text11 text21 text31 text42 text51',
 'text11 text21 text31 text42 text52',
 'text11 text21 text31 text42 text53',
 'text11 text21 text31 text43 text51',
 'text11 text21 text31 text43 text52',
 'text11 text21 text31 text43 text53',
 'text11 text21 text32 text41 text51',
 'text11 text21 text32 text41 text52',
 'text11 text21 text32 text41 text53',
 'text11 text21 text32 text42 text51',
 'text11 text21 text32 text42 text52',
 'text11 text21 text32 text42 text53',
 'text11 text21 text32 text43 text51',
 'text11 text21 text32 text43 text52',
  ...
 'text13 text23 text32 text42 text53',
 'text13 text23 text32 text43 text51',
 'text13 text23 text32 text43 text52',
 'text13 text23 text32 text43 text53']

For more details:

>>> list(itertools.product(*lists))

[('text11', 'text21', 'text31', 'text41', 'text51'),
 ('text11', 'text21', 'text31', 'text41', 'text52'),
 ('text11', 'text21', 'text31', 'text41', 'text53'),
 ('text11', 'text21', 'text31', 'text42', 'text51'),
 ('text11', 'text21', 'text31', 'text42', 'text52'),
 ('text11', 'text21', 'text31', 'text42', 'text53'),
 ('text11', 'text21', 'text31', 'text43', 'text51'),
 ('text11', 'text21', 'text31', 'text43', 'text52'),
 ('text11', 'text21', 'text31', 'text43', 'text53'),
 ...
]

CodePudding user response:

Besides sorting of list entries, the following might be what you are looking for:

list1 = ["text11", "text12", "text13"]
list2 = ["text21", "text22", "text23"]
list3 = ["text31", "text32"]

my_list = [list1, list2, list3]

tmp = set(my_list[0])
for i in range(1, len(my_list)):
    tmp = [x   ' '   y for x in tmp for y in my_list[i]]
    
print(tmp)

Output:

['text13 text21 text31', 'text13 text21 text32', 'text13 text22 text31', 'text13 text22 text32', 'text13 text23 text31', 'text13 text23 text32', 'text12 text21 text31', 'text12 text21 text32', 'text12 text22 text31', 'text12 text22 text32', 'text12 text23 text31', 'text12 text23 text32', 'text11 text21 text31', 'text11 text21 text32', 'text11 text22 text31', 'text11 text22 text32', 'text11 text23 text31', 'text11 text23 text32']

CodePudding user response:

  1. Combine the lists into a single list

  2. Then use the inbuilt combinations function

    from itertools import combinations

    # Combine all 3 lists into 1 list
    list4 = list1   list2   list3
    
    # Get all combinations of length 3 (since you want the items from the 3 lists)
    combos = combinations(list4,3)

    # Print the combinations
    for a in list(combos):
        # Since you want them separated by " ", use " " to join each list
        print ("   ".join(a))

CodePudding user response:

You are so close!!!! You said you can only do it when all the lists have the same length. Why not make this the case? Maybe use a "place-holder" character that you remove after forming the combinations? I'll let you think about that. ;-)

FYI: The approach I just hinted to will work, but it is not the most efficient. If you want to find the "correct" way to do it, I would look into recursion.

I noticed that you named one of your variables list. This is not a good idea because list is an already defined function. After you replace it's value, you may not be able to call it this may be okay in your program, but is generally bad practice and can cause unwanted side-effects.

The answers of the other people are correct, but I would suggest writing the function that finds the combinations yourself before using already written code. If you use that principal in general, you'll learn a lot more much quicker.

Have a great day!

  • Related