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