Cartesian product of a dictionary of lists
Ok, thanks @dfan for telling me I was looking in the wrong place. I've got it now:
from itertools import productdef my_product(inp): return (dict(zip(inp.keys(), values)) for values in product(*inp.values())
EDIT: after years more Python experience, I think a better solution is to accept kwargs
rather than a dictionary of inputs; the call style is more analogous to that of the original itertools.product
. Also I think writing a generator function, rather than a function that returns a generator expression, makes the code clearer. So:
def product_dict(**kwargs): keys = kwargs.keys() vals = kwargs.values() for instance in itertools.product(*vals): yield dict(zip(keys, instance))
and if you need to pass in a dict, list(product_dict(**mydict))
. The one notable change using kwargs
rather than an arbitrary input class is that it prevents the keys/values from being ordered, at least until Python 3.6.
Python 3 version of Seth's answer.
import itertoolsdef dict_product(dicts): """ >>> list(dict_product(dict(number=[1,2], character='ab'))) [{'character': 'a', 'number': 1}, {'character': 'a', 'number': 2}, {'character': 'b', 'number': 1}, {'character': 'b', 'number': 2}] """ return (dict(zip(dicts, x)) for x in itertools.product(*dicts.values()))
By the way, this is not a permutation. A permutation is a rearrangement of a list. This is an enumeration of possible selections from lists.
Edit: after remembering that it was called a Cartesian product, I came up with this:
import itertoolsoptions = {"number": [1,2,3], "color": ["orange","blue"] }product = [x for x in apply(itertools.product, options.values())]print([dict(zip(options.keys(), p)) for p in product])