首页 > 解决方案 > 列表嵌套字典的笛卡尔积

问题描述

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

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))

假设我有一本A字典

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

等等所有组合......我正在寻找一种优雅的方式来做到这一点。没有任何特定的性能限制,它们是小型字典。

标签: pythonpython-3.xcombinationsitertoolscartesian-product

解决方案


最终得到了任意嵌套字典的递归版本:

import itertools

def gen_combinations(d):
    keys, values = d.keys(), d.values()
    values_choices = (gen_combinations(v) if isinstance(v, dict) else v for v in values)
    for comb in itertools.product(*values_choices):
        yield dict(zip(keys, comb))


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

for c in gen_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}}

推荐阅读