字典的笛卡尔积

Gab*_*Chu 3 python dictionary cartesian-product

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

似乎可以通过使用itertoolsand来实现apply,但我不太清楚具体的实现。

输入:

region = {'east': 0.5, 'north': 0.20, 'south': 0.10, 'west': 0.20}
gender = {'female': 0.70, 'male': 0.30}
Run Code Online (Sandbox Code Playgroud)

期望的输出:

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}
Run Code Online (Sandbox Code Playgroud)

Wil*_*sem 5

两本词典

只需使用带有嵌套循环的字典理解:

{(k1,k2):v1*v2 for k1,v1 in region.items() for k2,v2 in gender.items()}
Run Code Online (Sandbox Code Playgroud)

所以在这里我们构造,对于每个k1,v1inregion和 for every k2,v2ingender字典中的一个元素,其键(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}
Run Code Online (Sandbox Code Playgroud)

您看到的事实是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) }
Run Code Online (Sandbox Code Playgroud)

导致:

>>> 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}
Run Code Online (Sandbox Code Playgroud)

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

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

    >>> 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}
    
    Run Code Online (Sandbox Code Playgroud)
  • “折叠”值的其他方式:

    >>> 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}
    
    Run Code Online (Sandbox Code Playgroud)