ozagon
ozagon

Reputation: 43

Get the product of lists inside a dict while retaining the same keys

I have the following dict:

my_dict = {'A': [1, 2], 'B': [1, 4]}

And I want to end up with a list of dicts like this:

[
    {'A': 1, 'B': 1},
    {'A': 1, 'B': 4},
    {'A': 2, 'B': 1},
    {'A': 2, 'B': 4}
]

So, I'm after the product of dict's lists, expressed as a list of dicts using the same keys as the incoming dict.

The closest I got was:

my_dict = {'A': [1, 2], 'B': [1, 4]}
it = []
for k in my_dict.keys():
    current = my_dict.pop(k)
    for i in current:
        it.append({k2: i2 for k2, i2 in my_dict.iteritems()})
        it[-1].update({k: i})

Which, apart from looking hideous, doesn't give me what I want:

[
    {'A': 1, 'B': [1, 4]}, 
    {'A': 2, 'B': [1, 4]}, 
    {'B': 1}, 
    {'B': 4}
]

If anyone feels like solving a riddle, I'd love to see how you'd approach it.

Upvotes: 3

Views: 607

Answers (4)

Raphaël Braud
Raphaël Braud

Reputation: 1519

With itertools:

>>> from itertools import product
>>> my_dict = {'A': [1, 2], 'B': [1, 4]}
>>> keys, items = zip(*my_dict.items())
>>> [dict(zip(keys, x)) for x in product(*items)]
[{'A': 1, 'B': 1}, {'A': 1, 'B': 4}, {'A': 2, 'B': 1}, {'A': 2, 'B': 4}]

Upvotes: 1

Kasravnd
Kasravnd

Reputation: 107307

you can use itertools.product function within a list comprehension :

>>> from itertools import product
>>> [dict(i) for i in product(*[[(i,k) for k in j] for i,j in my_dict.items()])]
[{'A': 1, 'B': 1}, {'A': 1, 'B': 4}, {'A': 2, 'B': 1}, {'A': 2, 'B': 4}]

You can get the pairs contain your key and values with the following list comprehension :

[(i,k) for k in j] for i,j in my_dict.items()]
[[('A', 1), ('A', 2)], [('B', 1), ('B', 4)]]

Then you can use product to calculate the product of the preceding lists and then convert them to dictionary with dict function.

Upvotes: 1

Ashwini Chaudhary
Ashwini Chaudhary

Reputation: 251001

You can use itertools.product for this, i.e calculate cartesian product of the value and then simply zip each of the them with the keys from the dictionary. Note that ordering of a dict's keys() and corresponding values() remains same if it is not modified in-between hence ordering won't be an issue here:

>>> from itertools import product
>>> my_dict = {'A': [1, 2], 'B': [1, 4]}
>>> keys = list(my_dict)
>>> [dict(zip(keys, p)) for p in product(*my_dict.values())]
[{'A': 1, 'B': 1}, {'A': 1, 'B': 4}, {'A': 2, 'B': 1}, {'A': 2, 'B': 4}]

Upvotes: 8

Augusto Hack
Augusto Hack

Reputation: 2170

Try this:

from itertools import product

def dict_product(values, first, second):
   return [
       {first: first_value, second: second_value}
       for first_value, second_value in product(values[first], values[second])
   ]

This is the result:

>>> dict_product({'A': [1, 2], 'B': [1, 4]}, 'A', 'B')
[{'A': 1, 'B': 1}, {'A': 1, 'B': 4}, {'A': 2, 'B': 1}, {'A': 2, 'B': 4}]

Upvotes: 0

Related Questions