计算3个字典的乘积并连接键和值

2024-04-26 23:10:55 发布

您现在位置:Python中文网/ 问答频道 /正文

假设我有3本不同的字典:

dict1 = {
  "A": "a"
}

dict2 = {
  "B": "b", 
  "C": "c",
  "D": "d", 
  "E": "e"
}

dict3 = {
  "F": "f", 
  "G": "g"
}

我想计算这些字典的乘积(不包括dict2和{})的乘积,并将键与_和值与' and '连接的键和值结合起来

所需的输出将是一个字典:

^{pr2}$

我看了itertools的文档,但我不明白如何才能获得所需的输出。在


Tags: and文档字典乘积itertoolspr2dict1dict2
3条回答

我创建了一个(不太好)函数来处理任意数量的字典。在

(解释如下)

import itertools as it

dict1 = {
  "A": "a"
}

dict2 = {
  "B": "b", 
  "C": "c",
  "D": "d", 
  "E": "e"
}

dict3 = {
  "F": "f", 
  "G": "g"
}



def custom_dict_product(dictionaries):
    return dict(zip(map("_".join, it.product(*map(dict.keys, dictionaries))), 
                    map(" and ".join, it.product(*map(dict.values, dictionaries)))))

result = custom_dict_product([dict1,dict2])
result.update(custom_dict_product([dict1,dict3]))
result.update(custom_dict_product([dict1,dict2,dict3]))
result
#{'A_B': 'a and b',
# 'A_B_F': 'a and b and f',
# 'A_B_G': 'a and b and g',
# 'A_C': 'a and c',
# 'A_C_F': 'a and c and f',
# 'A_C_G': 'a and c and g',
# 'A_D': 'a and d',
# 'A_D_F': 'a and d and f',
# 'A_D_G': 'a and d and g',
# 'A_E': 'a and e',
# 'A_E_F': 'a and e and f',
# 'A_E_G': 'a and e and g',
# 'A_F': 'a and f',
# 'A_G': 'a and g'}

函数接受给定的字典并获取它们的键和值,这是由map(dict.keys, dictionaries))map(dict.values, dictionaries))完成的。第一次通话的结果

^{pr2}$

然后,使用join将该列表中的元组强制到您所需的结构中(并再次对每个元素执行映射调用):

"_".join(('A', 'C'))
# 'A_C'
list(map("_".join, it.product(*map(dict.keys, [dict1,dict2]))))
# ['A_C', 'A_E', 'A_B', 'A_D']

最后,通过调用zip将得到的两个列表转换为(keys, values)的元组,并交给字典的创建。在

完成这项工作的函数是^{}。 首先,下面是如何打印出产品dict1 x dict2 x dict3

for t in product(dict1.items(), dict2.items(), dict3.items()): 
     k, v = zip(*t) 
     print("_".join(k), "-", " and ".join(v))   

输出:

^{pr2}$

现在,只需填充一个result字典:

result = {}
for t in product(dict1.items(), dict2.items(), dict3.items()): 
     k, v = zip(*t) 
     result["_".join(k)] = " and ".join(v)

现在,您可以将dict1 x dict2和{}的乘积添加到这个字典中,这两个产品的计算更加简单。在


根据@ShadowRanger的评论,以下是完整的片段:

import itertools
import pprint


dict1 = {
  "A": "a"
}

dict2 = {
  "B": "b",
  "C": "c",
  "D": "d",
  "E": "e"
}

dict3 = {
  "F": "f",
  "G": "g"
}


result = {}
for dicts in ((dict1, dict2), (dict1, dict3), (dict1, dict2, dict3)):
    for t in itertools.product(*(d.items() for d in dicts)):
        k, v = zip(*t)
        result["_".join(k)] = " and ".join(v)

pprint.pprint(result)

输出:

{'A_B': 'a and b',
 'A_B_F': 'a and b and f',
 'A_B_G': 'a and b and g',
 'A_C': 'a and c',
 'A_C_F': 'a and c and f',
 'A_C_G': 'a and c and g',
 'A_D': 'a and d',
 'A_D_F': 'a and d and f',
 'A_D_G': 'a and d and g',
 'A_E': 'a and e',
 'A_E_F': 'a and e and f',
 'A_E_G': 'a and e and g',
 'A_F': 'a and f',
 'A_G': 'a and g'}

要生成所有对,可以使用两个递归生成器函数:一个用于查找字典的整体组合,另一个用于对键和值:

def pair_dicts(data, c):
   if not data:
     keys, values = zip(*c)
     yield ('_'.join(keys), ' and '.join(values))
   else:
     for i in data[0]:
        yield from pair_dicts(data[1:], c+[i])

def combos(d, c = []):
  if len(c) == len(d):
    yield c
  else:
    if len(c) > 1:
      yield c
    for i in d:
      if all(h != i for h in c):
         yield from combos(d, c+[i])

new_d = [[list(c.items()) for c in i] for i in combos([dict1, dict2, dict3])]
final_result = dict(i for b in new_d for i in pair_dicts(b, []))

输出:

^{pr2}$

相关问题 更多 >