Set*_*son 52 python generator combinatorics
我正在尝试编写一些代码来测试一堆输入参数的笛卡尔积.
我看过了itertools
,但它的product
功能并不完全是我想要的.是否有一个简单明显的方法来获取具有任意数量的键和每个值中的任意数量的元素的字典,然后产生具有下一个排列的字典?
输入:
options = {"number": [1,2,3], "color": ["orange","blue"] }
print list( my_product(options) )
Run Code Online (Sandbox Code Playgroud)
示例输出:
[ {"number": 1, "color": "orange"},
{"number": 1, "color": "blue"},
{"number": 2, "color": "orange"},
{"number": 2, "color": "blue"},
{"number": 3, "color": "orange"},
{"number": 3, "color": "blue"}
]
Run Code Online (Sandbox Code Playgroud)
Set*_*son 50
好的,谢谢@dfan告诉我,我在找错了地方.我现在知道了:
from itertools import product
def my_product(inp):
return (dict(zip(inp.keys(), values)) for values in product(*inp.values())
Run Code Online (Sandbox Code Playgroud)
编辑:经过多年的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))
Run Code Online (Sandbox Code Playgroud)
如果你需要传递一个词典,list(product_dict(**mydict))
.使用kwargs
而不是任意输入类的一个值得注意的变化是,它阻止了键/值的排序,至少在Python 3.6之前.
Tar*_*sch 17
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()))
Run Code Online (Sandbox Code Playgroud)
顺便说一句,这不是一种排列.排列是列表的重新排列.这是列表中可能选择的枚举.
编辑:在记住它被称为笛卡尔积之后,我想出了这个:
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]
Run Code Online (Sandbox Code Playgroud)