列表字典的笛卡尔积

时间:2011-03-08 03:57:13

标签: python generator combinatorics

我正在尝试编写一些代码来测试一堆输入参数的笛卡尔积。

我查看了itertools,但其product功能并不完全符合我的要求。是否有一个简单明显的方法来获取具有任意数量的键的字典在每个值中的任意数量的元素,然后产生具有下一个排列的字典?

输入:

options = {"number": [1,2,3], "color": ["orange","blue"] }
print list( my_product(options) )

示例输出:

[ {"number": 1, "color": "orange"},
  {"number": 1, "color": "blue"},
  {"number": 2, "color": "orange"},
  {"number": 2, "color": "blue"},
  {"number": 3, "color": "orange"},
  {"number": 3, "color": "blue"}
]

4 个答案:

答案 0 :(得分:46)

好的,谢谢@dfan告诉我我在找错了地方。我现在知道了:

from itertools import product
def my_product(inp):
    return (dict(zip(inp.keys(), values)) for values in product(*inp.values())

编辑:经过多年的Python经验,我认为更好的解决方案是接受kwargs而不是输入词典;呼叫方式更类似于原始itertools.product的方式。另外我认为编写生成器函数而不是返回生成器表达式的函数会使代码更清晰。所以:

def product_dict(**kwargs):
    keys = kwargs.keys()
    vals = kwargs.values()
    for instance in itertools.product(*vals):
        yield dict(zip(keys, instance))

如果你需要传递dict,list(product_dict(**mydict))。使用kwargs而不是任意输入类的一个值得注意的变化是,它阻止了键/值的排序,至少在Python 3.6之前。

答案 1 :(得分:16)

{3}}的Python 3版本。

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()))

答案 2 :(得分:6)

顺便说一句,这不是一种排列。排列是列表的重新排列。这是列表中可能选择的枚举。

编辑:在记住它被称为笛卡尔积之后,我想出了这个:

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]

答案 3 :(得分:2)

# 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)]

结果

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}
]