How to generate all combination from values in dict of lists in Python
Question:
I would like to generate all combinations of values which are in lists indexed in a dict:
{'A':['D','E'],'B':['F','G','H'],'C':['I','J']}
Each time, one item of each dict entry would be picked and combined to items from other keys, so I have:
['D','F','I']
['D','F','J']
['D','G','I']
['D','G','J']
['D','H','I']
...
['E','H','J']
I know there is a something to generate combinations of items in list in itertools
but I don’t think I can use it here since I have different “pools” of values.
Is there any existing solution to do this, or how should I proceed to do it myself, I am quite stuck with this nested structure.
Answers:
import itertools as it
my_dict={'A':['D','E'],'B':['F','G','H'],'C':['I','J']}
allNames = sorted(my_dict)
combinations = it.product(*(my_dict[Name] for Name in allNames))
print(list(combinations))
Which prints:
[('D', 'F', 'I'), ('D', 'F', 'J'), ('D', 'G', 'I'), ('D', 'G', 'J'), ('D', 'H', 'I'), ('D', 'H', 'J'), ('E', 'F', 'I'), ('E', 'F', 'J'), ('E', 'G', 'I'), ('E', 'G', 'J'), ('E', 'H', 'I'), ('E', 'H', 'J')]
as a complement, here is a 3-liner that does it in pure python so that you get the idea, but itertools is indeed more efficient.
res = [[]]
for _, vals in my_dict.items():
res = [x+[y] for x in res for y in vals]
print(res)
from itertools import combinations
a=['I1','I2','I3','I4','I5']
list(combinations(a,2))
The output will be:
[('I1', 'I2'),
('I1', 'I3'),
('I1', 'I4'),
('I1', 'I5'),
('I2', 'I3'),
('I2', 'I4'),
('I2', 'I5'),
('I3', 'I4'),
('I3', 'I5'),
('I4', 'I5')]
If you want to keep the key:value
in the permutations you can use:
import itertools
keys, values = zip(*my_dict.items())
permutations_dicts = [dict(zip(keys, v)) for v in itertools.product(*values)]
this will provide you a list of dicts with the permutations:
print(permutations_dicts)
[{'A':'D', 'B':'F', 'C':'I'},
{'A':'D', 'B':'F', 'C':'J'},
...
]
Disclaimer: not exactly what the OP was asking, but google send me here looking for that. If you want to obtain what OP is asking you should just remove the dict part in the list comprehension, i.e.
permutations_dicts = [v for v in itertools.product(*values)]
How about using ParameterGrid from scikit-learn? It creates a generator over which you can iterate in a normal for loop. In each iteration, you will have a dictionary containing the current parameter combination.
from sklearn.model_selection import ParameterGrid
params = {'A':['D','E'],'B':['F','G','H'],'C':['I','J']}
param_grid = ParameterGrid(params)
for dict_ in param_grid:
# Do something with the current parameter combination in ``dict_``
print(dict_["A"])
print(dict_["B"])
print(dict_["C"])
I would like to generate all combinations of values which are in lists indexed in a dict:
{'A':['D','E'],'B':['F','G','H'],'C':['I','J']}
Each time, one item of each dict entry would be picked and combined to items from other keys, so I have:
['D','F','I']
['D','F','J']
['D','G','I']
['D','G','J']
['D','H','I']
...
['E','H','J']
I know there is a something to generate combinations of items in list in itertools
but I don’t think I can use it here since I have different “pools” of values.
Is there any existing solution to do this, or how should I proceed to do it myself, I am quite stuck with this nested structure.
import itertools as it
my_dict={'A':['D','E'],'B':['F','G','H'],'C':['I','J']}
allNames = sorted(my_dict)
combinations = it.product(*(my_dict[Name] for Name in allNames))
print(list(combinations))
Which prints:
[('D', 'F', 'I'), ('D', 'F', 'J'), ('D', 'G', 'I'), ('D', 'G', 'J'), ('D', 'H', 'I'), ('D', 'H', 'J'), ('E', 'F', 'I'), ('E', 'F', 'J'), ('E', 'G', 'I'), ('E', 'G', 'J'), ('E', 'H', 'I'), ('E', 'H', 'J')]
as a complement, here is a 3-liner that does it in pure python so that you get the idea, but itertools is indeed more efficient.
res = [[]]
for _, vals in my_dict.items():
res = [x+[y] for x in res for y in vals]
print(res)
from itertools import combinations
a=['I1','I2','I3','I4','I5']
list(combinations(a,2))
The output will be:
[('I1', 'I2'),
('I1', 'I3'),
('I1', 'I4'),
('I1', 'I5'),
('I2', 'I3'),
('I2', 'I4'),
('I2', 'I5'),
('I3', 'I4'),
('I3', 'I5'),
('I4', 'I5')]
If you want to keep the key:value
in the permutations you can use:
import itertools
keys, values = zip(*my_dict.items())
permutations_dicts = [dict(zip(keys, v)) for v in itertools.product(*values)]
this will provide you a list of dicts with the permutations:
print(permutations_dicts)
[{'A':'D', 'B':'F', 'C':'I'},
{'A':'D', 'B':'F', 'C':'J'},
...
]
Disclaimer: not exactly what the OP was asking, but google send me here looking for that. If you want to obtain what OP is asking you should just remove the dict part in the list comprehension, i.e.
permutations_dicts = [v for v in itertools.product(*values)]
How about using ParameterGrid from scikit-learn? It creates a generator over which you can iterate in a normal for loop. In each iteration, you will have a dictionary containing the current parameter combination.
from sklearn.model_selection import ParameterGrid
params = {'A':['D','E'],'B':['F','G','H'],'C':['I','J']}
param_grid = ParameterGrid(params)
for dict_ in param_grid:
# Do something with the current parameter combination in ``dict_``
print(dict_["A"])
print(dict_["B"])
print(dict_["C"])