列表的嵌套字典的笛卡尔乘积

问题描述

我有一些代码可以为列表字典生成所有组合

import itertools
import collections

def gen_combinations(d):
    keys, values = d.keys(), d.values()
    combinations = itertools.product(*values)

    for c in combinations:
        yield dict(zip(keys, c))

假设我有一个词典ALIKE

A = {'a': [0, 1],
     'b': [2, 3, 4]}

它产生:

{'a': 0, 'b': 2}
{'a': 0, 'b': 3}
{'a': 0, 'b': 4}
{'a': 1, 'b': 2}
{'a': 1, 'b': 3}
{'a': 1, 'b': 4}

现在我希望它与如下列表的嵌套字典一起使用

B = {'s1': {'a': [0, 1],
            'b': [0, 1, 2] },
     's2': {'c': [0, 1],
            'd': [0, 1] }}

这应该会产生类似以下内容的结果:

{'s1': {'a': 0, 'b': 0},
 's2': {'c': 0, 'd': 0}}

{'s1': {'a': 0, 'b': 0},
 's2': {'c': 0, 'd': 1}}

{'s1': {'a': 0, 'b': 0},
 's2': {'c': 1, 'd': 0}}

{'s1': {'a': 0, 'b': 0},
 's2': {'c': 1, 'd': 1}}

以此类推,适用于所有组合. 我在找一种优雅的方式来做这件事。没有任何特定的性能限制,它们是小词典。


解决方案

只需为外字典中的每个键创建gen_combinations()的输出乘积:

def gen_dict_combinations(d):
    keys, values = d.keys(), d.values()
    for c in itertools.product(*(gen_combinations(v) for v in values)):
        yield dict(zip(keys, c))

这基本上是相同的模式,只不过现在不是直接使用values,而是使用gen_combinations()的输出:

>>> for c in gen_dict_combinations(B):
...     print(c)
...
{'s1': {'a': 0, 'b': 0}, 's2': {'c': 0, 'd': 0}}
{'s1': {'a': 0, 'b': 0}, 's2': {'c': 0, 'd': 1}}
{'s1': {'a': 0, 'b': 0}, 's2': {'c': 1, 'd': 0}}
{'s1': {'a': 0, 'b': 0}, 's2': {'c': 1, 'd': 1}}
{'s1': {'a': 0, 'b': 1}, 's2': {'c': 0, 'd': 0}}
{'s1': {'a': 0, 'b': 1}, 's2': {'c': 0, 'd': 1}}
{'s1': {'a': 0, 'b': 1}, 's2': {'c': 1, 'd': 0}}
{'s1': {'a': 0, 'b': 1}, 's2': {'c': 1, 'd': 1}}
{'s1': {'a': 0, 'b': 2}, 's2': {'c': 0, 'd': 0}}
{'s1': {'a': 0, 'b': 2}, 's2': {'c': 0, 'd': 1}}
{'s1': {'a': 0, 'b': 2}, 's2': {'c': 1, 'd': 0}}
{'s1': {'a': 0, 'b': 2}, 's2': {'c': 1, 'd': 1}}
{'s1': {'a': 1, 'b': 0}, 's2': {'c': 0, 'd': 0}}
{'s1': {'a': 1, 'b': 0}, 's2': {'c': 0, 'd': 1}}
{'s1': {'a': 1, 'b': 0}, 's2': {'c': 1, 'd': 0}}
{'s1': {'a': 1, 'b': 0}, 's2': {'c': 1, 'd': 1}}
{'s1': {'a': 1, 'b': 1}, 's2': {'c': 0, 'd': 0}}
{'s1': {'a': 1, 'b': 1}, 's2': {'c': 0, 'd': 1}}
{'s1': {'a': 1, 'b': 1}, 's2': {'c': 1, 'd': 0}}
{'s1': {'a': 1, 'b': 1}, 's2': {'c': 1, 'd': 1}}
{'s1': {'a': 1, 'b': 2}, 's2': {'c': 0, 'd': 0}}
{'s1': {'a': 1, 'b': 2}, 's2': {'c': 0, 'd': 1}}
{'s1': {'a': 1, 'b': 2}, 's2': {'c': 1, 'd': 0}}
{'s1': {'a': 1, 'b': 2}, 's2': {'c': 1, 'd': 1}}

相关文章