为n种不同类型创建笛卡尔积

时间:2017-06-10 21:16:30

标签: python python-2.7

考虑我有一个dict,其中包含由键表示的n种不同类型:x1, x2 ..xn

为简单起见,我们举一个小例子:

{"x1":["foo1", "goo1" ,"doo1"], "x2":["foo2","goo2"]}

我想计算上述笛卡尔积。我的输出应该是:

{"output":[{"x1":"foo1", "x2":"foo2"}, {"x1":"foo1", "x2":"goo2"}, {"x1":"goo1", "x2":"foo2"} , {"x1":"goo1", "x2":"goo2"}, {"x1":"doo1", "x2":"foo2"} {"x1":"doo1", "x2":"goo2"}]}

我是否应该遍历输入字典键中的每个unique pair并计算其笛卡尔积并附加其值? 如果出现另一个值,我如何连接其余的值让我们说x3?

在这种方法中,我将计算x2 * x2值的笛卡尔积 然后是x2 * x3值,如何将结果合并为x1 * x2 * x3?

你能想到更简单的算法和有效的算法吗?或者这应该是这样的?

2 个答案:

答案 0 :(得分:4)

您可以使用itertools.product获取笛卡尔积。 要为新的dicts重建键值对,您可以先冻结键的顺序(.keys.values在所有Python版本中都不能保证排序,除非dict是在取出笛卡尔积之前,通过调用列表来改变它。笛卡尔积的值现在维持键的顺序,现在可以使用zip 安全地构建生成的词组的键值对:

from itertools import product
from pprint import pprint

dct = {"x1":["foo1", "goo1" ,"doo1"], "x2":["foo2","goo2"]}

keys = list(dct)
lst = [dict(zip(keys, vals)) for vals in product(*[dct[k] for k in keys])]
pprint(lst)
[{'x1': 'foo1', 'x2': 'foo2'},
 {'x1': 'foo1', 'x2': 'goo2'},
 {'x1': 'goo1', 'x2': 'foo2'},
 {'x1': 'goo1', 'x2': 'goo2'},
 {'x1': 'doo1', 'x2': 'foo2'},
 {'x1': 'doo1', 'x2': 'goo2'}]

这将扩展为原始列表包含的值列表。

答案 1 :(得分:0)

您可以在理解中使用product模块中的itertools

from itertools import product

a = {"x1":["foo1", "goo1" ,"doo1"], "x2":["foo2","goo2"]}
final = [{i:j for i, j in zip(a.keys(), k)} for k in product(*a.values())]
# Or:
# final = [dict(zip(a.keys(), k)) for k in product(*a.values())]
# Or:
# final = list(map(lambda x: dict(zip(a.keys(), x)), product(*a.values())))

print(final)

输出:

[{'x1': 'foo1', 'x2': 'foo2'},
 {'x1': 'foo1', 'x2': 'goo2'},
 {'x1': 'goo1', 'x2': 'foo2'},
 {'x1': 'goo1', 'x2': 'goo2'},
 {'x1': 'doo1', 'x2': 'foo2'},
 {'x1': 'doo1', 'x2': 'goo2'}]