【问题标题】:Combination of nested dictionaries with arbitrary lengths in pythonpython中任意长度的嵌套字典的组合
【发布时间】:2022-01-07 17:26:25
【问题描述】:

我正在寻找一个可以使用嵌套字典并生成值的组合/乘积的函数。

我的查询与此处指定的问题类似,但我似乎无法调整他们的答案以满足我的需求: Cartesian product of nested dictionaries of lists

我希望有这样的输入:

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

在这个例子中,输出是一个人可以占据的“状态”列表

  • 列表(输入)的任何两个元素不应位于返回列表(输出)的同一元素中,例如某人不能同时在国家 1 和国家 2
  • 字典(输入)中的所有键都应在列表(输出)的相同元素中返回,例如有人在国家 1 并且也在健康状态。如果该健康状况是“乳腺癌”,他们也处于第 1 阶段或第 2 阶段

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

【问题讨论】:

    标签: python combinations itertools cartesian-product


    【解决方案1】:

    你可以使用递归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}}}]]
    

    【讨论】:

      猜你喜欢
      • 2014-12-12
      • 1970-01-01
      • 2018-11-28
      • 2016-01-30
      • 1970-01-01
      • 2023-03-18
      • 1970-01-01
      • 1970-01-01
      • 2019-01-11
      相关资源
      最近更新 更多