Reputation: 481
I want to return all possible key combinations of a python dictionary. In my case, it is a two-levels hierarchy dictionary.
My first attempt seems like a pseudo-code-like sequence of for loops. It works but it is ugly and it gets really painful if I have a lot of data.
I want a do the same task with the dict-comprehension approach.
Here is my attempt. Using this technique, I could easily end up with many - way too many - for loops.
dic = {
'Sex' : {'Man' : 0, 'Woman' : 1},
'Age group' : {'0-14yrs' : 0, '15-25yrs' : 1, '26-35yrs' : 2}
}
for x in range(len(list(dic['Sex'].keys()))):
for y in range(len(list(dic['Age group'].keys()))):
sex = list(dic['Sex'].keys())[x]
age = list(dic['Age group'].keys())[y]
print(sex,age)
Man 0-14yrs
Man 15-25yrs
Man 26-35yrs
Woman 0-14yrs
Woman 15-25yrs
Woman 26-35yrs
Upvotes: 3
Views: 242
Reputation: 531075
I would use itertools.product
.
for sex, age in itertools.product(dic['Sex'], dic['Age group']):
print(sex, age)
product
returns an generator of tuples, which you can do with what you like.
For an arbitrary dict
, where you don't necessarily know the keys or their ordering in advance, I would tag each value with its key first.
>>> for t in list(itertools.product(*[[(k, v) for v in dic[k] ] for k in dic])):
... print(t)
...
(('Age group', '15-25yrs'), ('Sex', 'Woman'))
(('Age group', '15-25yrs'), ('Sex', 'Man'))
(('Age group', '0-14yrs'), ('Sex', 'Woman'))
(('Age group', '0-14yrs'), ('Sex', 'Man'))
(('Age group', '26-35yrs'), ('Sex', 'Woman'))
(('Age group', '26-35yrs'), ('Sex', 'Man'))
Now you at least know the "type" of each value in the corresponding tuple; it doesn't depend on any specific ordering involving the original dict
.
Upvotes: 3
Reputation: 4622
If you want your solution to be general as possible, you can do something like that:
from itertools import product
product(*dic.values())
That will give you a generator with the following values:
[('Man', '0-14yrs'), ('Man', '15-25yrs'), ('Man', '26-35yrs'), ('Woman', '0-14yrs'), ('Woman', '15-25yrs'), ('Woman', '26-35yrs')]
Upvotes: 1