How to generate all combination from values in dict of lists in Python
Asked Answered
A

5

37

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.

Anima answered 2/8, 2016 at 13:28 Comment(7)
Then you should try to write code to do so, and come back if you have problems.Possessory
itertools.product(*yourdict.values())Devlin
dictionaries are not ordered! please clarify.Zellner
I tried to write code but I got stuck, I am actually looking for a existing solution not to waste my time on this ... I don't understand why you say dictionnaries are not ordered, I know that and this has nothing to do with my problem, I want combinations, not permutations. @Devlin : Thank you I'm trying it.Anima
You assumed an order. Why is D the first letter, and not... say F?Zellner
You assumed this ... I could have written F before D ... this doesn't change the problem ... Btw, itertools.product didn't workAnima
Of course I did. Your description wasn't clear. BTW, why do you use a list then? Use a set.Zellner
A
46
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')]
Artistry answered 2/8, 2016 at 13:39 Comment(1)
need to sort the dict first otherwise values can be associated with the wrong keyEnsoll
P
63

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)]
Perigon answered 21/4, 2020 at 3:28 Comment(0)
A
46
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')]
Artistry answered 2/8, 2016 at 13:39 Comment(1)
need to sort the dict first otherwise values can be associated with the wrong keyEnsoll
B
15

ParameterGrid from scikit-learn creates a generator. Each for loop iteration will give you 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:
    print(dict_)
    

# output
{'A': 'D', 'B': 'F', 'C': 'I'}
...
Breastbone answered 28/4, 2020 at 16:58 Comment(2)
This is neat if you already are working in an environment with scikit-learn. The itertools is part of the standard library, though.Optimize
This was the best answer in my case, thank you.Inexact
T
1

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)
Threequarter answered 13/7, 2018 at 16:22 Comment(0)
P
1
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')]
Plumbiferous answered 19/12, 2018 at 5:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.