Furlings
Furlings

Reputation: 113

Convert dict to list of dict for each combinations

I have a dict looks like this :

my_dict = {
    "a":[1, 2, 3],
    "b":[10],
    "c":[4, 5],
    "d":[11]
}

And I would like to obtain a list containig all combinations keeping keys and value like this:

result = [
    {"a":1, "b":10, "c":4, "d":11},
    {"a":1, "b":10, "c":5, "d":11},
    {"a":2, "b":10, "c":4, "d":11},
    {"a":2, "b":10, "c":5, "d":11},
    {"a":3, "b":10, "c":4, "d":11},
    {"a":3, "b":10, "c":5, "d":11}
]

Do someone have a solution for this ? Is there any existing solution to do this, or how should I proceed to do it myself ?

Thank you.

Upvotes: 0

Views: 96

Answers (5)

Mateen Ulhaq
Mateen Ulhaq

Reputation: 27201

Try:

def permute(d):
    k = d.keys()
    perms = itertools.product(*d.values())
    return [dict(zip(k, v)) for v in perms]

Example usage:

>>> d = {'a': [1, 2, 3], 'b': [10], 'c': [4, 5], 'd': [11]}

>>> pprint(permute(d))
[{'a': 1, 'b': 10, 'c': 4, 'd': 11},
 {'a': 1, 'b': 10, 'c': 5, 'd': 11},
 {'a': 2, 'b': 10, 'c': 4, 'd': 11},
 {'a': 2, 'b': 10, 'c': 5, 'd': 11},
 {'a': 3, 'b': 10, 'c': 4, 'd': 11},
 {'a': 3, 'b': 10, 'c': 5, 'd': 11}]

Upvotes: 0

Mark Tolonen
Mark Tolonen

Reputation: 177610

itertools.product produces the combinations of a list of iterators.

dict.values() gets the list needed.

For each combination, zip up the dict.keys() with the combination.

Use a list comprehension to collect them up:

from itertools import product
from pprint import pprint

my_dict = {
    "a":[1, 2, 3],
    "b":[10],
    "c":[4, 5],
    "d":[11]
}

result = [dict(zip(my_dict,i)) for i in product(*my_dict.values())]
pprint(result)

Output:

[{'a': 1, 'b': 10, 'c': 4, 'd': 11},
 {'a': 1, 'b': 10, 'c': 5, 'd': 11},
 {'a': 2, 'b': 10, 'c': 4, 'd': 11},
 {'a': 2, 'b': 10, 'c': 5, 'd': 11},
 {'a': 3, 'b': 10, 'c': 4, 'd': 11},
 {'a': 3, 'b': 10, 'c': 5, 'd': 11}]

Upvotes: 0

fferri
fferri

Reputation: 18940

A task for itertools.product:

>>> from itertools import product
>>> for dict_items in product(*[product([k],v) for k, v in my_dict.items()]):
...    print(dict(dict_items))

{'a': 1, 'b': 10, 'c': 4, 'd': 11}
{'a': 1, 'b': 10, 'c': 5, 'd': 11}
{'a': 2, 'b': 10, 'c': 4, 'd': 11}
{'a': 2, 'b': 10, 'c': 5, 'd': 11}
{'a': 3, 'b': 10, 'c': 4, 'd': 11}
{'a': 3, 'b': 10, 'c': 5, 'd': 11}

Small explanation:

The inner product(...) will expand the dict to a list such as [[(k1, v11), (k1, v12), ...], [(k2, v21), (k2, v22), ...], ...].

The outer product(...) will reassemble the items lists by choosing one tuple from each list.

dict(...) will create a dictionary from a sequence of (k1, v#), (k2, v#), ... tuples.

Upvotes: 2

Joe
Joe

Reputation: 12417

You can use:

from itertools import product
allNames = sorted(my_dict)
values= list(product(*(my_dict[Name] for Name in allNames)))
d = list(dict(zip(['a','b','c','d'],i)) for i in values)

Output:

[{'a': 1, 'c': 4, 'b': 10, 'd': 11}, 
{'a': 1, 'c': 5, 'b': 10, 'd': 11}, 
{'a': 2, 'c': 4, 'b': 10, 'd': 11}, 
{'a': 2, 'c': 5, 'b': 10, 'd': 11}, 
{'a': 3, 'c': 4, 'b': 10, 'd': 11}, 
{'a': 3, 'c': 5, 'b': 10, 'd': 11}]

Upvotes: 0

DatHydroGuy
DatHydroGuy

Reputation: 1116

Assuming that you are only interested in my_dict having 4 keys, it is simple enough to use nested for loops:

my_dict = {
    "a": [1, 2, 3],
    "b": [10],
    "c": [4, 5],
    "d": [11]
}

result = []
for a_val in my_dict['a']:
    for b_val in my_dict['b']:
        for c_val in my_dict['c']:
            for d_val in my_dict['d']:
                result.append({'a': a_val, 'b': b_val, 'c': c_val, 'd': d_val})

print(result)

This gives the expected result.

Upvotes: 0

Related Questions