python 中任意长度的嵌套字典的组合

Combination of nested dictionaries with arbitrary lengths in python

我正在寻找一个函数,它将采用嵌套字典,并生成值的组合/乘积。

我的查询与此处指定的问题类似,但我似乎无法根据我的需要调整答案:

我希望有这样的输入:

d = {
  "country": [1, 2],
  "health_state": [
    {"healthy": [1]},
    {"breast cancer": {"stage": [1, 2]}}
  ]
}

产生如下输出:

[
{{"country":1},{"health state":{"healthy":1}}},
{{"country":2},{"health state":{"healthy":1}}},
{{"country":1},{"health state":{"breast cancer":{"stage":1}}}},
{{"country":1},{"health state":{"breast cancer":{"stage":2}}}},
{{"country":2},{"health state":{"breast cancer":{"stage":1}}}},
{{"country":2},{"health state":{"breast cancer":{"stage":2}}}}
]

在这个例子中,输出的是一个人可以占据'states'的列表

我可以设想一个需要大量 for 循环的解决方案,检查元素是字典、列表还是两者都不是,但这似乎效率低下,尤其是对于深度嵌套的字典。我怀疑可能有使用 itertools.product 和递归的更优雅的解决方案?

您可以使用递归 itertools.product:

import itertools as it
d = {'country': [1, 2], 'health_state': [{'healthy': [1]}, {'breast cancer': {'stage': [1, 2]}}]}
def c_prod(d):
  if isinstance(d, list):
     for i in d:
        yield from ([i] if not isinstance(i, (dict, list)) else c_prod(i))
  else:
     for i in it.product(*map(c_prod, d.values())):
        yield dict(zip(d.keys(), i))

print(list(c_prod(d)))

输出:

[{'country': 1, 'health_state': {'healthy': 1}}, 
 {'country': 1, 'health_state': {'breast cancer': {'stage': 1}}}, 
 {'country': 1, 'health_state': {'breast cancer': {'stage': 2}}}, 
 {'country': 2, 'health_state': {'healthy': 1}}, 
 {'country': 2, 'health_state': {'breast cancer': {'stage': 1}}}, 
 {'country': 2, 'health_state': {'breast cancer': {'stage': 2}}}]

上面代码的输出生成了一个字典列表,但是您想要的输出反映了一个字典列表列表 (list[list[dict]]),因此,可以进行最终转换:

r = [[{j:k} for j, k in i.items()] for i in c_prod(d)]

输出:

[[{'country': 1}, {'health_state': {'healthy': 1}}], [{'country': 1}, {'health_state': {'breast cancer': {'stage': 1}}}], [{'country': 1}, {'health_state': {'breast cancer': {'stage': 2}}}], [{'country': 2}, {'health_state': {'healthy': 1}}], [{'country': 2}, {'health_state': {'breast cancer': {'stage': 1}}}], [{'country': 2}, {'health_state': {'breast cancer': {'stage': 2}}}]]