Cartesian product of a dictionary of lists

前端 未结 4 1904
有刺的猬
有刺的猬 2020-11-27 12:08

I\'m trying to write some code to test out the Cartesian product of a bunch of input parameters.

I\'ve looked at itertools, but its product

相关标签:
4条回答
  • 2020-11-27 12:15

    Ok, thanks @dfan for telling me I was looking in the wrong place. I've got it now:

    from itertools import product
    def 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.

    0 讨论(0)
  • 2020-11-27 12:36
    # I would like to do
    keys,values = options.keys(), options.values()
    # but I am not sure that the keys and values would always
    # be returned in the same relative order. Comments?
    keys = []
    values = []
    for k,v in options.iteritems():
        keys.append(k)
        values.append(v)
    
    import itertools
    opts = [dict(zip(keys,items)) for items in itertools.product(*values)]
    

    results in

    opts = [
        {'color': 'orange', 'number': 1},
        {'color': 'orange', 'number': 2},
        {'color': 'orange', 'number': 3},
        {'color': 'blue', 'number': 1},
        {'color': 'blue', 'number': 2},
        {'color': 'blue', 'number': 3}
    ]
    
    0 讨论(0)
  • 2020-11-27 12:39

    Python 3 version of Seth's answer.

    import itertools
    
    def 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()))
    
    0 讨论(0)
  • 2020-11-27 12:41

    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 itertools
    options = {"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]
    
    0 讨论(0)
提交回复
热议问题