笛卡尔词典的产品

时间:2017-05-17 07:54:38

标签: python python-3.x dictionary cartesian-product

我正在尝试编写一些python代码来获得以下输出,所有排列。 regiongender的值是概率,result反映了给定事件组合的乘积。

似乎可以通过使用itertoolsapply来实现,但我不太确定具体的实现。

输入:

region = {'east': 0.5, 'north': 0.20, 'south': 0.10, 'west': 0.20}
gender = {'female': 0.70, 'male': 0.30}

期望的输出:

result = {('east','female'):0.35, 
('east','male'):0.15,
('north','female'):0.14,
('north','male'):0.06,
('south','female'):0.07,
('south','male'):0.03,
('west','female'):0.14,
('west','male'):0.06}

2 个答案:

答案 0 :(得分:4)

两个词典

只需使用嵌套循环字典理解

{(k1,k2):v1*v2 for k1,v1 in region.items() for k2,v2 in gender.items()}

因此,我们为k1,v1中的每个region以及k2,v2gender中的每个(k1,k2)构建一个映射到键v1*v2的字典中的元素>>> {(k1,k2):v1*v2 for k1,v1 in region.items() for k2,v2 in gender.items()} {('north', 'female'): 0.13999999999999999, ('west', 'female'): 0.13999999999999999, ('east', 'female'): 0.35, ('south', 'male'): 0.03, ('north', 'male'): 0.06, ('east', 'male'): 0.15, ('south', 'female'): 0.06999999999999999, ('west', 'male'): 0.06}

这会产生:

0.13999...

您看到0.14而不是from operator import mul, getitem from functools import reduce from itertools import product, starmap def cartesian_dictionary(*args,fold=mul): return { ks : reduce(fold,starmap(getitem,zip(args,ks))) for ks in product(*args) }的事实是由于使用浮点舍入错误,而与字典理解本身无关。

任意数量的词典

您还可能想要计算任意数量字典的笛卡尔积(请注意,这将按指数方式缩放,因此字典数量因内存限制而受到限制)。在这种情况下,您可以使用以下过程:

>>> cartesian_dictionary({'east': 0.5, 'north': 0.20, 'south': 0.10, 'west': 0.20},{'female': 0.70, 'male': 0.30})
{('east', 'female'): 0.35, ('west', 'female'): 0.13999999999999999, ('south', 'male'): 0.03, ('north', 'male'): 0.06, ('south', 'female'): 0.06999999999999999, ('north', 'female'): 0.13999999999999999, ('west', 'male'): 0.06, ('east', 'male'): 0.15}

导致:

>>> cartesian_dictionary({'a':2,'b':3},{'c':0.5,'d':1},{'e':1,'f':2})
{('b', 'c', 'e'): 1.5, ('a', 'c', 'f'): 2.0, ('b', 'd', 'f'): 6, ('a', 'c', 'e'): 1.0, ('b', 'd', 'e'): 3, ('a', 'd', 'f'): 4, ('b', 'c', 'f'): 3.0, ('a', 'd', 'e'): 2}

但它提供了额外的灵活性:

  • 三个或更多字典,例如:

    >>> cartesian_dictionary({'a':2,'b':3},{'c':0.5,'d':1},fold=operator.add)
    {('a', 'd'): 3, ('b', 'd'): 4, ('b', 'c'): 3.5, ('a', 'c'): 2.5}
    
  • 其他方式"折叠"值:

    js/main

答案 1 :(得分:3)

如果你想使用itertools,你可以这样做:

from itertools import product

d = {(reg[0], gen[0]): reg[1]*gen[1]
     for (reg, gen) in product(region.items(), gender.items())}

虽然我非常喜欢Willem Van Onsem's answer

如果你没有将所有结果存储在字典中,那么itertools版本可能是有益的,但只是迭代它们,对结果做一些事情并丢弃它们。类似的东西:

for (reg, gen) in product(region.items(), gender.items()):
    key = (reg[0], gen[0])
    value = reg[1]*gen[1]
    # do something with key, value