来自不同大小集合的元素的所有可能组合

时间:2019-09-06 09:27:27

标签: python dictionary itertools

我正在创建供私人使用的工具,但遇到了一个复杂的组合问题。

我有7个类似格式的子字典:

{"D1": {"A": 1, "B": 3, "C":6},
 "D2": {"D": 4},
 "D3": {"E": 8, "F": 12, "G": 2}.
 "D4": {"H": 9, "I": 3}.
 "D5": {"J": 2},
 "D6": {"K": 8, "L": 1},
 "D7": {"M": 2}}

我需要生成所有可能的字典,这些字典将以这种格式组合每个字典中的1个元素:

[{"D1": "A", "D2": "D", "D3": "E", "D4": "H", "D5": "J", "D6": "K", "D7": "M"},
 {"D1": "A", "D2": "D", "D3": "F", "D4": "I", "D5": "J", "D6": "L", "D7": "M"},
 and all other possible combinations]

输出应为所有DX字典中的元素的所有可能唯一组合的列表。 我可能可以使用一些非常复杂,外观难看的嵌套嵌套有很多if的循环来解决此问题,但是在itertools或类似工具中可能有一种非常不错的方法。

对有效完成该任务有帮助吗? 需要根据大量此类命令来重复执行此任务,因此性能是关键。 谢谢!

3 个答案:

答案 0 :(得分:2)

看起来有点复杂,但是很简单:

import itertools

D = [D1, D2, D3, D4, ...]

dicts = [
    dict(zip([f'D{i+1}' for i in range(len(D))], iter)) 
    for iter in itertools.product(*[list(d.keys()) for d in D])
]

dict_1 = dicts[0]
dict_2 = dicts[1]
...
dicts = [
    {'D1': 'A', 'D2': 'D', 'D3': 'E', 'D4': 'H'},
    {'D1': 'A', 'D2': 'D', 'D3': 'E', 'D4': 'I'},
    {'D1': 'A', 'D2': 'D', 'D3': 'F', 'D4': 'H'},
    {'D1': 'A', 'D2': 'D', 'D3': 'F', 'D4': 'I'},
    ...
]

工作方式:

生成所有键组合

itertools.product(*[list(d.keys()) for d in D])

使用适当的字典名称组合组合

zip([f'D{i+1}' for i in range(len(D))], iter))

将这两个部分结合起来,然后将每个部分转换成字典

[
    dict(zip([f'D{i+1}' for i in range(len(D))], iter)) 
    for iter in itertools.product(*[list(d.keys()) for d in D])
]

答案 1 :(得分:1)

您想要的是字典的笛卡尔积。 幸运的是,itertools定义了一个product函数,正是该函数。

dict用作迭代时,将产生其键,因此product(D1, D2, ...)将直接产生键的元组,例如('A', 'D', 'F', ...)

您需要进行一些调整才能准确获得所需的输出:

from pprint import pprint
import itertools

dicts = [
    {"A": 1, "B": 3, "C":6},
    {"D": 4},
    {"E": 8, "F": 12, "G": 2},
    {"H": 9, "I": 3}
]

r = [
    {f"D{i}": key for i, key in enumerate(x, 1)}
    for x in itertools.product(*dicts)
]
pprint(r)

输出:

[{'D1': 'A', 'D2': 'D', 'D3': 'E', 'D4': 'H'},
 {'D1': 'A', 'D2': 'D', 'D3': 'E', 'D4': 'I'},
 {'D1': 'A', 'D2': 'D', 'D3': 'F', 'D4': 'H'},
 {'D1': 'A', 'D2': 'D', 'D3': 'F', 'D4': 'I'},
 {'D1': 'A', 'D2': 'D', 'D3': 'G', 'D4': 'H'},
 {'D1': 'A', 'D2': 'D', 'D3': 'G', 'D4': 'I'},
 {'D1': 'B', 'D2': 'D', 'D3': 'E', 'D4': 'H'},
 {'D1': 'B', 'D2': 'D', 'D3': 'E', 'D4': 'I'},
 {'D1': 'B', 'D2': 'D', 'D3': 'F', 'D4': 'H'},
 {'D1': 'B', 'D2': 'D', 'D3': 'F', 'D4': 'I'},
 {'D1': 'B', 'D2': 'D', 'D3': 'G', 'D4': 'H'},
 {'D1': 'B', 'D2': 'D', 'D3': 'G', 'D4': 'I'},
 {'D1': 'C', 'D2': 'D', 'D3': 'E', 'D4': 'H'},
 {'D1': 'C', 'D2': 'D', 'D3': 'E', 'D4': 'I'},
 {'D1': 'C', 'D2': 'D', 'D3': 'F', 'D4': 'H'},
 {'D1': 'C', 'D2': 'D', 'D3': 'F', 'D4': 'I'},
 {'D1': 'C', 'D2': 'D', 'D3': 'G', 'D4': 'H'},
 {'D1': 'C', 'D2': 'D', 'D3': 'G', 'D4': 'I'}]

答案 2 :(得分:1)

itertools product是你的朋友:

from itertools import product

d = {"D1": {"A": 1, "B": 3, "C":6}, 
     "D2": {"D": 4},  
     "D3": {"E": 8, "F": 12, "G": 2}, 
     "D4": {"H": 9, "I": 3}, 
     "D5": {"J": 2}, 
     "D6": {"K": 8, "L": 1}, 
     "D7": {"M": 2}}

res = []
for c in product(*(v.keys() for _, v in d.items())):
  res.append(dict(zip(d.keys(), c)))

列表综合版本为:

res = [dict(zip(d.keys(), c)) for c in product(*(v.keys() for _, v in d.items()))]

产生:

[{'D1': 'A', 'D2': 'D', 'D3': 'E', 'D4': 'H', 'D5': 'J', 'D6': 'K', 'D7': 'M'},
 {'D1': 'A', 'D2': 'D', 'D3': 'E', 'D4': 'H', 'D5': 'J', 'D6': 'L', 'D7': 'M'},
 {'D1': 'A', 'D2': 'D', 'D3': 'E', 'D4': 'I', 'D5': 'J', 'D6': 'K', 'D7': 'M'},
 {'D1': 'A', 'D2': 'D', 'D3': 'E', 'D4': 'I', 'D5': 'J', 'D6': 'L', 'D7': 'M'},
 {'D1': 'A', 'D2': 'D', 'D3': 'F', 'D4': 'H', 'D5': 'J', 'D6': 'K', 'D7': 'M'},
 {'D1': 'A', 'D2': 'D', 'D3': 'F', 'D4': 'H', 'D5': 'J', 'D6': 'L', 'D7': 'M'},
 {'D1': 'A', 'D2': 'D', 'D3': 'F', 'D4': 'I', 'D5': 'J', 'D6': 'K', 'D7': 'M'},
 {'D1': 'A', 'D2': 'D', 'D3': 'F', 'D4': 'I', 'D5': 'J', 'D6': 'L', 'D7': 'M'},
 {'D1': 'A', 'D2': 'D', 'D3': 'G', 'D4': 'H', 'D5': 'J', 'D6': 'K', 'D7': 'M'},
 {'D1': 'A', 'D2': 'D', 'D3': 'G', 'D4': 'H', 'D5': 'J', 'D6': 'L', 'D7': 'M'},
 {'D1': 'A', 'D2': 'D', 'D3': 'G', 'D4': 'I', 'D5': 'J', 'D6': 'K', 'D7': 'M'},
 {'D1': 'A', 'D2': 'D', 'D3': 'G', 'D4': 'I', 'D5': 'J', 'D6': 'L', 'D7': 'M'},
 {'D1': 'B', 'D2': 'D', 'D3': 'E', 'D4': 'H', 'D5': 'J', 'D6': 'K', 'D7': 'M'},
 {'D1': 'B', 'D2': 'D', 'D3': 'E', 'D4': 'H', 'D5': 'J', 'D6': 'L', 'D7': 'M'},
 {'D1': 'B', 'D2': 'D', 'D3': 'E', 'D4': 'I', 'D5': 'J', 'D6': 'K', 'D7': 'M'},
 {'D1': 'B', 'D2': 'D', 'D3': 'E', 'D4': 'I', 'D5': 'J', 'D6': 'L', 'D7': 'M'},
 {'D1': 'B', 'D2': 'D', 'D3': 'F', 'D4': 'H', 'D5': 'J', 'D6': 'K', 'D7': 'M'},
 {'D1': 'B', 'D2': 'D', 'D3': 'F', 'D4': 'H', 'D5': 'J', 'D6': 'L', 'D7': 'M'},
 {'D1': 'B', 'D2': 'D', 'D3': 'F', 'D4': 'I', 'D5': 'J', 'D6': 'K', 'D7': 'M'},
 {'D1': 'B', 'D2': 'D', 'D3': 'F', 'D4': 'I', 'D5': 'J', 'D6': 'L', 'D7': 'M'},
 {'D1': 'B', 'D2': 'D', 'D3': 'G', 'D4': 'H', 'D5': 'J', 'D6': 'K', 'D7': 'M'},
 {'D1': 'B', 'D2': 'D', 'D3': 'G', 'D4': 'H', 'D5': 'J', 'D6': 'L', 'D7': 'M'},
 {'D1': 'B', 'D2': 'D', 'D3': 'G', 'D4': 'I', 'D5': 'J', 'D6': 'K', 'D7': 'M'},
 {'D1': 'B', 'D2': 'D', 'D3': 'G', 'D4': 'I', 'D5': 'J', 'D6': 'L', 'D7': 'M'},
 {'D1': 'C', 'D2': 'D', 'D3': 'E', 'D4': 'H', 'D5': 'J', 'D6': 'K', 'D7': 'M'},
 {'D1': 'C', 'D2': 'D', 'D3': 'E', 'D4': 'H', 'D5': 'J', 'D6': 'L', 'D7': 'M'},
 {'D1': 'C', 'D2': 'D', 'D3': 'E', 'D4': 'I', 'D5': 'J', 'D6': 'K', 'D7': 'M'},
 {'D1': 'C', 'D2': 'D', 'D3': 'E', 'D4': 'I', 'D5': 'J', 'D6': 'L', 'D7': 'M'},
 {'D1': 'C', 'D2': 'D', 'D3': 'F', 'D4': 'H', 'D5': 'J', 'D6': 'K', 'D7': 'M'},
 {'D1': 'C', 'D2': 'D', 'D3': 'F', 'D4': 'H', 'D5': 'J', 'D6': 'L', 'D7': 'M'},
 {'D1': 'C', 'D2': 'D', 'D3': 'F', 'D4': 'I', 'D5': 'J', 'D6': 'K', 'D7': 'M'},
 {'D1': 'C', 'D2': 'D', 'D3': 'F', 'D4': 'I', 'D5': 'J', 'D6': 'L', 'D7': 'M'},
 {'D1': 'C', 'D2': 'D', 'D3': 'G', 'D4': 'H', 'D5': 'J', 'D6': 'K', 'D7': 'M'},
 {'D1': 'C', 'D2': 'D', 'D3': 'G', 'D4': 'H', 'D5': 'J', 'D6': 'L', 'D7': 'M'},
 {'D1': 'C', 'D2': 'D', 'D3': 'G', 'D4': 'I', 'D5': 'J', 'D6': 'K', 'D7': 'M'},
 {'D1': 'C', 'D2': 'D', 'D3': 'G', 'D4': 'I', 'D5': 'J', 'D6': 'L', 'D7': 'M'}]

优缺点

(+)与其他答案不同,该答案不依赖于遵循D<i>模式的子对象的命名;他们可以叫什么。

(-)必须保留字典的顺序,因此您需要Python 3.5 +