Skip to content Skip to sidebar Skip to footer

Creating Cartesian Product For N Different Types

Consider I have a dict holding n different types represented by keys:x1, x2 ..xn For simplicity let's take a small example: {'x1':['foo1', 'goo1' ,'doo1'], 'x2':['foo2','goo2']} I

Solution 1:

You can use itertools.product to get the cartesian product. To reconstruct the key-value pairs for the new dicts, you can first freeze the order of keys (.keys and .values ordering is not guaranteed across all Python versions unless dict is not altered) by calling list on it before taking the cartesian product. The values from the cartesian product now maintain the order of the keys and the key-value pairs for the resulting dicts can now be safely constructed with zip:

from itertools import product
from pprint import pprint

dct = {"x1":["foo1", "goo1" ,"doo1"], "x2":["foo2","goo2"]}

keys = list(dct)
lst = [dict(zip(keys, vals)) for vals in product(*[dct[k] for k in keys])]
pprint(lst)

[{'x1': 'foo1', 'x2': 'foo2'},
 {'x1': 'foo1', 'x2': 'goo2'},
 {'x1': 'goo1', 'x2': 'foo2'},
 {'x1': 'goo1', 'x2': 'goo2'},
 {'x1': 'doo1', 'x2': 'foo2'},
 {'x1': 'doo1', 'x2': 'goo2'}]

This will scale to as many value lists as the original list contains.

Solution 2:

You can use product from itertools module within a comprehension:

from itertools import product

a = {"x1":["foo1", "goo1" ,"doo1"], "x2":["foo2","goo2"]}
final= [{i:j for i, j inzip(a.keys(), k)} for k in product(*a.values())]
# Or:
# final= [dict(zip(a.keys(), k)) for k in product(*a.values())]
# Or:
# final= list(map(lambda x: dict(zip(a.keys(), x)), product(*a.values())))

print(final)

Output:

[{'x1': 'foo1', 'x2': 'foo2'},
 {'x1': 'foo1', 'x2': 'goo2'},
 {'x1': 'goo1', 'x2': 'foo2'},
 {'x1': 'goo1', 'x2': 'goo2'},
 {'x1': 'doo1', 'x2': 'foo2'},
 {'x1': 'doo1', 'x2': 'goo2'}]

Post a Comment for "Creating Cartesian Product For N Different Types"