簡體   English   中英

字典的笛卡爾積

[英]Cartesian product of dictionaries

我正在嘗試編寫一些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}

兩本詞典

只需將字典理解與嵌套循環一起使用:

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

因此,在這里我們為region中的每個k1,v1gender中的每個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}
  • “折疊”值的其他方式:

     >>> 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())}

雖然我非常喜歡Willem Van Onsem 的回答

如果您沒有將所有結果存儲在字典中,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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM