假设我有3种不同的字典:
dict1 = {
"A": "a"
}
dict2 = {
"B": "b",
"C": "c",
"D": "d",
"E": "e"
}
dict3 = {
"F": "f",
"G": "g"
}
我想计算这些字典的乘积(不包括dict2
和dict3
之间的乘积),并组合键和值(其中键与_
串联,而值与) ' 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
的文档,但无法理解如何获得所需的输出。
答案 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 dict2
和dict1 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'}