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

时间:2019-04-11 16:08:00

标签: python

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

dict1 = {
  "A": "a"
}

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

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

我想计算这些字典的乘积(不包括dict2dict3之间的乘积),并组合键和值(其中键与_串联,而值与) ' and '

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

{
  # dict1 x dict2 
  "A_B": "a and b", 
  "A_C": "a and c",
  "A_D": "a and d",
  "A_E": "a and e",

  # dict1 x dict3  
  "A_F": "a and f",
  "A_G": "a and g",

  # dict1 x dict2 x dict3 
  "A_B_F": "a and b and f",
  "A_B_G": "a and b and g",
  "A_C_F": "a and c and f",
  "A_C_G": "a and c and g",
  "A_D_F": "a and d and f",
  "A_D_G": "a and d and g",
  "A_E_F": "a and e and f",
  "A_E_G": "a and e and g"
} 

我看了itertools的文档,但无法理解如何获得所需的输出。

4 个答案:

答案 0 :(得分:8)

将执行此功能的功能是itertools.product。 首先,这是打印产品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))   

输出:

A_B_F - a and b and f
A_B_G - a and b and g
A_C_F - a and c and f
A_C_G - a and c and g
A_D_F - a and d and f
A_D_G - a and d and g
A_E_F - a and e and f
A_E_G - a and e and g

现在,只需填充result字典:

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

您现在可以将dict1 x dict2dict1 x dict3产品添加到此字典中,它们甚至更易于计算。


根据@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'}

答案 1 :(得分:1)

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

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, []))

输出:

{'A_B': 'a and b', 'A_C': 'a and c', 'A_D': 'a and d', 'A_E': 'a and e', 'A_B_F': 'a and b and f', 'A_B_G': 'a and b and g', 'A_C_F': 'a and c and f', 'A_C_G': 'a and c and g', 'A_D_F': 'a and d and f', 'A_D_G': 'a and d and g', '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', 'A_F_B': 'a and f and b', 'A_F_C': 'a and f and c', 'A_F_D': 'a and f and d', 'A_F_E': 'a and f and e', 'A_G_B': 'a and g and b', 'A_G_C': 'a and g and c', 'A_G_D': 'a and g and d', 'A_G_E': 'a and g and e', 'B_A': 'b and a', 'C_A': 'c and a', 'D_A': 'd and a', 'E_A': 'e and a', 'B_A_F': 'b and a and f', 'B_A_G': 'b and a and g', 'C_A_F': 'c and a and f', 'C_A_G': 'c and a and g', 'D_A_F': 'd and a and f', 'D_A_G': 'd and a and g', 'E_A_F': 'e and a and f', 'E_A_G': 'e and a and g', 'B_F': 'b and f', 'B_G': 'b and g', 'C_F': 'c and f', 'C_G': 'c and g', 'D_F': 'd and f', 'D_G': 'd and g', 'E_F': 'e and f', 'E_G': 'e and g', 'B_F_A': 'b and f and a', 'B_G_A': 'b and g and a', 'C_F_A': 'c and f and a', 'C_G_A': 'c and g and a', 'D_F_A': 'd and f and a', 'D_G_A': 'd and g and a', 'E_F_A': 'e and f and a', 'E_G_A': 'e and g and a', 'F_A': 'f and a', 'G_A': 'g and a', 'F_A_B': 'f and a and b', 'F_A_C': 'f and a and c', 'F_A_D': 'f and a and d', 'F_A_E': 'f and a and e', 'G_A_B': 'g and a and b', 'G_A_C': 'g and a and c', 'G_A_D': 'g and a and d', 'G_A_E': 'g and a and e', 'F_B': 'f and b', 'F_C': 'f and c', 'F_D': 'f and d', 'F_E': 'f and e', 'G_B': 'g and b', 'G_C': 'g and c', 'G_D': 'g and d', 'G_E': 'g and e', 'F_B_A': 'f and b and a', 'F_C_A': 'f and c and a', 'F_D_A': 'f and d and a', 'F_E_A': 'f and e and a', 'G_B_A': 'g and b and a', 'G_C_A': 'g and c and a', 'G_D_A': 'g and d and a', 'G_E_A': 'g and e and a'}

答案 2 :(得分:0)

我创建了一个(不是很好)的函数来使用任意数量的词典来完成您的任务。

(以下说明)

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))完成。第一次通话的结果

list(it.product(*map(dict.keys, [dict1,dict2])))
# [('A', 'C'), ('A', 'E'), ('A', 'B'), ('A', 'D')]

然后使用join将此列表中的元组强制为所需的结构(并再次进行映射调用以对每个元素执行此操作):

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

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

答案 3 :(得分:0)

这是一个肮脏但可行的解决方案,它使用了itertools

from itertools import product, combinations


# create a list and sum dict to be used later
t = [dict1, dict2, dict3] 
k = {}
for d in t:
    k.update(d)


# iterate over "i" order of combinations ("dict1_X" or "dict1_X_Y") and 
# the cartesian product of keys for each combination

results = {}
for i in range(2, 4):
    a = [
        [
            results.update({"_".join(y): " and ".join([k[j] for j in y])})
            for y in product(*x)
        ]
        for x in combinations(t, i) 
        if dict1 in x
    ]

results

输出:

{'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'}