首页 > 解决方案 > 在 Python 中转换嵌套的字典列表

问题描述

我想将嵌套的字典列表转换为子结构。并找到一种强大的方法来做到这一点。结构:

nested_list = [
  {
     "id" : "fruit",
     "name" : "apple"
  },
  {
     "name": "fruit"
  },
  {
     "id" : "fruit",
     "name" : "grape"
  },
  {
     "id" : "fruit",
     "name" : "pineapple"
  },
  {
     "name": "vehicle"
  },
  {
    "id" : "vehicle",
     "name": "car"
  },
  {
    "id" : "car",
     "name": "sedan"
  },
] 

进入:

{
  "vehicle": {
    "car": {
        "sedan" : {}
     }
  },
  "fruit" : {
     "apple": {},
    "grape": {},
    "pineapple": {}
  }
}

请注意,在这种情况下,它可以下降两级。但它也可以深入三层。例如一个额外的条目:

{ 
   "id" : "sedan", 
   "name": "mini sedan" 
}

到目前为止,我的方法是:

for category in nested_list:
    if 'id' not in category:
        d[category['name']] = {}

for category in nested_list:
    if 'id' in category and category['id'] in d:
        d[category['id']][category['name']] = {}
    elif 'id' in category and category['id'] not in d:
        for k, v in d.items():
            if category['id'] in v:
                d[k][category['id']] = {category['name']: {}}
    # If there are not top level key then do nothing
    else:
        pass

它适用于这种情况。问题是它不够健壮。我正在考虑递归,但无法破解它。有人可以帮忙吗?谢谢

标签: pythonlistdictionary

解决方案


解决方案

您可以使用collections.defaultdictdict.setdefault

from collections import defaultdict

nested_list = [
    {
        "id": "fruit",
        "name": "apple"
    },
    {
        "name": "fruit"
    },
    {
        "id": "fruit",
        "name": "grape"
    },
    {
        "id": "fruit",
        "name": "pineapple"
    },
    {
        "name": "vehicle"
    },
    {
        "id": "vehicle",
        "name": "car"
    },
    {
        "id": "car",
        "name": "sedan"
    },
    {
        "id": "sedan",
        "name": "mini sedan"
    },
]

working_dict = defaultdict(dict)
result_dict = {}

for item in nested_list:
    name = item['name']
    if 'id' in item:
        id_ = item['id']
        working_dict[id_].setdefault(name, working_dict[name])
    else:
        result_dict[name] = working_dict[name]
print(working_dict)
print(result_dict)

输出:

defaultdict(<class 'dict'>, {'fruit': {'apple': {}, 'grape': {}, 'pineapple': {}}, 'apple': {}, 'grape': {}, 'pineapple': {}, 'vehicle': {'car': {'sedan': {'mini sedan': {}}}}, 'car': {'sedan': {'mini sedan': {}}}, 'sedan': {'mini sedan': {}}, 'mini sedan': {}})
{'fruit': {'apple': {}, 'grape': {}, 'pineapple': {}}, 'vehicle': {'car': {'sedan': {'mini sedan': {}}}}}

解释

  • 这个想法:dict是可变的。
  • working_dict是所有"id"s 的参考表。
  • 如果没有这样的id,注册{}它。
  • 并将没有id字段的元素作为根元素注册到result_dict.

附加

不想用collections.defaultdict就只能用dict.setdefault。但它更冗长。

working_dict = {}
result_dict = {}

for item in nested_list:
    name = item['name']
    if 'id' in item:
        id_ = item['id']
        working_dict.setdefault(id_, {}).setdefault(name, working_dict.setdefault(name, {}))
    else:
        result_dict[name] = working_dict.setdefault(name, {})
print(result_dict)

推荐阅读