Make all possible combinations of values from lists different size

Viewed 64

I have a Python dict with lists of different length as key values.

{
    'basis1': ['key11', 'key12', 'key13', 'key14'],
    'basis2': ['key21'],
    'basis3': ['key31', 'key32', 'key33'],
    'basis4': ['key41', 'key42'],
    ...'basisX': ['keyX1', ..., 'keyXX']
}

How can I get all possible combinations of all dict key values (one value from each key to one value from another key)? I mean not only "basis1 + basis2 + ... basisX" values but also e.g. "basis2 + basis1 + basis3" and "basis3 + basisX" values.

I used to iterate with a "product" func from "itertools" for generating keywords by predetermined formulas. But there is a limitation because of the formulas and the number of lists that are in these formulas. But I need to make it so that does not depend on the number of lists that will be fed to the input of the function, as well as mix in a different order the values from the lists.

from itertools import product
...
...
...
# Each [keysX] is a list of values

    formula1 = [keys0] + [keys1]
    formula2 = [keys0] + [keys2]
    formula3 = [keys1] + [keys2]
    formula4 = [keys0] + [keys1] + [keys2]
    all_keywords = []

    for combo in product(*formula1):
        all_keywords.append(" ".join(combo))

    for combo in product(*formula2):
        all_keywords.append(" ".join(combo))

    for combo in product(*formula3):
        all_keywords.append(" ".join(combo))

    for combo in product(*formula4):
        all_keywords.append(" ".join(combo))
2 Answers

Note: Considering it is a permutations of all the elements of a powerset, the resulting iterable will be huge. So it is recommended, not to store it in memory, unless necessary. I have used generators for that reason.

You can use the following:

from itertools import chain, combinations, permutations

def powerset(iterable):
    '''
    >>> list(powerset([1, 2, 3]))
    [(1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)]
    '''
    iterable = list(iterable)
    return chain.from_iterable(
        combinations(iterable, r)
        for r, _ in enumerate(iterable, start=1)
    )

def perm_powerset(iterable):
    '''
    Given a powerset, returns a generator consisting
    all possible permutations of each element in the powerset.
    '''
    for each_set in powerset(iterable):
        for elem in permutations(each_set):
            yield elem

d = {'k1': [1, 2], 'k2': [3], 'k4': [4]}

for elem in perm_powerset(chain.from_iterable(d.values())):
    print(elem)

Output:

(1,)
(2,)
(3,)
(4,)
(1, 2)
(2, 1)
(1, 3)
(3, 1)
(1, 4)
(4, 1)
(2, 3)
(3, 2)
(2, 4)
(4, 2)
(3, 4)
(4, 3)
(1, 2, 3)
(1, 3, 2)
(2, 1, 3)
(2, 3, 1)
(3, 1, 2)
(3, 2, 1)
(1, 2, 4)
(1, 4, 2)
(2, 1, 4)
(2, 4, 1)
(4, 1, 2)
(4, 2, 1)
(1, 3, 4)
(1, 4, 3)
(3, 1, 4)
(3, 4, 1)
(4, 1, 3)
(4, 3, 1)
(2, 3, 4)
(2, 4, 3)
(3, 2, 4)
(3, 4, 2)
(4, 2, 3)
(4, 3, 2)
(1, 2, 3, 4)
(1, 2, 4, 3)
(1, 3, 2, 4)
(1, 3, 4, 2)
(1, 4, 2, 3)
(1, 4, 3, 2)
(2, 1, 3, 4)
(2, 1, 4, 3)
(2, 3, 1, 4)
(2, 3, 4, 1)
(2, 4, 1, 3)
(2, 4, 3, 1)
(3, 1, 2, 4)
(3, 1, 4, 2)
(3, 2, 1, 4)
(3, 2, 4, 1)
(3, 4, 1, 2)
(3, 4, 2, 1)
(4, 1, 2, 3)
(4, 1, 3, 2)
(4, 2, 1, 3)
(4, 2, 3, 1)
(4, 3, 1, 2)
(4, 3, 2, 1)

This piece of code generates what you need. First, you need to have all combination of values, then for each combination generate all products of keywords.

from itertools import product, chain, combinations

my_dict = {
    'basis1': ['key11', 'key12', 'key13', 'key14'],
    'basis2': ['key21'],
    'basis3': ['key31', 'key32', 'key33'],
    'basis4': ['key41', 'key42']}

list_of_values = list(my_dict.values())

all_combs_of_lists = [combinations(list_of_values, r) for r in range(1, len(list_of_values) + 1)]
list_combinations = list(chain.from_iterable(all_combs_of_lists))

all_keywords = [" ".join(combo) for item in list_combinations for combo in product(*item)]
        
print(all_keywords)

Output:

['key11', 'key12', 'key13', 'key14', 'key21', 'key31', 'key32', 'key33', 'key41', 'key42', 'key11 key21', 'key12 key21', 'key13 key21', 'key14 key21', 'key11 key31', 'key11 key32', 'key11 key33', 'key12 key31', 'key12 key32', 'key12 key33', 'key13 key31', 'key13 key32', 'key13 key33', 'key14 key31', 'key14 key32', 'key14 key33', 'key11 key41', 'key11 key42', 'key12 key41', 'key12 key42', 'key13 key41', 'key13 key42', 'key14 key41', 'key14 key42', 'key21 key31', 'key21 key32', 'key21 key33', 'key21 key41', 'key21 key42', 'key31 key41', 'key31 key42', 'key32 key41', 'key32 key42', 'key33 key41', 'key33 key42', 'key11 key21 key31', 'key11 key21 key32', 'key11 key21 key33', 'key12 key21 key31', 'key12 key21 key32', 'key12 key21 key33', 'key13 key21 key31', 'key13 key21 key32', 'key13 key21 key33', 'key14 key21 key31', 'key14 key21 key32', 'key14 key21 key33', 'key11 key21 key41', 'key11 key21 key42', 'key12 key21 key41', 'key12 key21 key42', 'key13 key21 key41', 'key13 key21 key42', 'key14 key21 key41', 'key14 key21 key42', 'key11 key31 key41', 'key11 key31 key42', 'key11 key32 key41', 'key11 key32 key42', 'key11 key33 key41', 'key11 key33 key42', 'key12 key31 key41', 'key12 key31 key42', 'key12 key32 key41', 'key12 key32 key42', 'key12 key33 key41', 'key12 key33 key42', 'key13 key31 key41', 'key13 key31 key42', 'key13 key32 key41', 'key13 key32 key42', 'key13 key33 key41', 'key13 key33 key42', 'key14 key31 key41', 'key14 key31 key42', 'key14 key32 key41', 'key14 key32 key42', 'key14 key33 key41', 'key14 key33 key42', 'key21 key31 key41', 'key21 key31 key42', 'key21 key32 key41', 'key21 key32 key42', 'key21 key33 key41', 'key21 key33 key42', 'key11 key21 key31 key41', 'key11 key21 key31 key42', 'key11 key21 key32 key41', 'key11 key21 key32 key42', 'key11 key21 key33 key41', 'key11 key21 key33 key42', 'key12 key21 key31 key41', 'key12 key21 key31 key42', 'key12 key21 key32 key41', 'key12 key21 key32 key42', 'key12 key21 key33 key41', 'key12 key21 key33 key42', 'key13 key21 key31 key41', 'key13 key21 key31 key42', 'key13 key21 key32 key41', 'key13 key21 key32 key42', 'key13 key21 key33 key41', 'key13 key21 key33 key42', 'key14 key21 key31 key41', 'key14 key21 key31 key42', 'key14 key21 key32 key41', 'key14 key21 key32 key42', 'key14 key21 key33 key41', 'key14 key21 key33 key42']
Related