[英]Cartesian product of a dictionary of lists
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
function is not exactly what I want. 我看过
itertools
,但是它的product
功能并不是我想要的。 Is there a simple obvious way to take a dictionary with an arbitrary number of keys and an arbitrary number of elements in each value, and then yield a dictionary with the next permutation? 是否有一种简单明了的方法来获取一个字典,每个字典中包含任意数量的键和每个值中任意数量的元素,然后生成具有下一个排列的字典?
Input: 输入:
options = {"number": [1,2,3], "color": ["orange","blue"] }
print list( my_product(options) )
Example output: 输出示例:
[ {"number": 1, "color": "orange"},
{"number": 1, "color": "blue"},
{"number": 2, "color": "orange"},
{"number": 2, "color": "blue"},
{"number": 3, "color": "orange"},
{"number": 3, "color": "blue"}
]
Ok, thanks @dfan for telling me I was looking in the wrong place. 好的,谢谢@dfan告诉我我在错误的地方看。 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; 编辑 :经过多年的Python经验,我认为一个更好的解决方案是接受
kwargs
而不是输入字典。 the call style is more analogous to that of the original itertools.product
. 调用样式与原始
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))
. 如果需要传递字典,请使用
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. 使用
kwargs
而不是任意输入类的一个显着变化是,它至少在Python 3.6之前阻止键/值被排序。
Python 3 version of Seth's answer . 塞思答案的 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()))
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]
# 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}
]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.