字典的笛卡尔积
Cartesian product of dictionaries
我正在尝试编写一些 python 代码来获得以下输出,所有排列。 region
和 gender
的值是概率,result
反映给定事件组合的乘积。
好像可以用itertools
和apply
来实现,但是具体实现不太清楚
输入:
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}
两部词典
简单地使用 字典理解 和嵌套循环:
{(k1,k2):v1*v2 for k1,v1 in region.items() for k2,v2 in gender.items()}
所以这里我们为region
中的每个k1,v1
和gender
中的每个k2,v2
构造一个字典中具有键(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}
"fold" 值的其他方式:
>>> 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}
如果你想使用 itertools,你可以这样做:
from itertools import product
d = {(reg[0], gen[0]): reg[1]*gen[1]
for (reg, gen) in product(region.items(), gender.items())}
虽然我更喜欢。
如果您不将所有结果存储在字典中,而是迭代它们,对结果做一些处理并丢弃它们,那么 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
我正在尝试编写一些 python 代码来获得以下输出,所有排列。 region
和 gender
的值是概率,result
反映给定事件组合的乘积。
好像可以用itertools
和apply
来实现,但是具体实现不太清楚
输入:
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}
两部词典
简单地使用 字典理解 和嵌套循环:
{(k1,k2):v1*v2 for k1,v1 in region.items() for k2,v2 in gender.items()}
所以这里我们为region
中的每个k1,v1
和gender
中的每个k2,v2
构造一个字典中具有键(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}
"fold" 值的其他方式:
>>> 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}
如果你想使用 itertools,你可以这样做:
from itertools import product
d = {(reg[0], gen[0]): reg[1]*gen[1]
for (reg, gen) in product(region.items(), gender.items())}
虽然我更喜欢
如果您不将所有结果存储在字典中,而是迭代它们,对结果做一些处理并丢弃它们,那么 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