猿问

在 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

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


杨魅力
浏览 92回答 2
2回答

MYYA

溶液您可以使用 和 :collections.defaultdictdict.setdefaultfrom collections import defaultdictnested_list = [&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; "id": "fruit",&nbsp; &nbsp; &nbsp; &nbsp; "name": "apple"&nbsp; &nbsp; },&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; "name": "fruit"&nbsp; &nbsp; },&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; "id": "fruit",&nbsp; &nbsp; &nbsp; &nbsp; "name": "grape"&nbsp; &nbsp; },&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; "id": "fruit",&nbsp; &nbsp; &nbsp; &nbsp; "name": "pineapple"&nbsp; &nbsp; },&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; "name": "vehicle"&nbsp; &nbsp; },&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; "id": "vehicle",&nbsp; &nbsp; &nbsp; &nbsp; "name": "car"&nbsp; &nbsp; },&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; "id": "car",&nbsp; &nbsp; &nbsp; &nbsp; "name": "sedan"&nbsp; &nbsp; },&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; "id": "sedan",&nbsp; &nbsp; &nbsp; &nbsp; "name": "mini sedan"&nbsp; &nbsp; },]working_dict = defaultdict(dict)result_dict = {}for item in nested_list:&nbsp; &nbsp; name = item['name']&nbsp; &nbsp; if 'id' in item:&nbsp; &nbsp; &nbsp; &nbsp; id_ = item['id']&nbsp; &nbsp; &nbsp; &nbsp; working_dict[id_].setdefault(name, working_dict[name])&nbsp; &nbsp; else:&nbsp; &nbsp; &nbsp; &nbsp; 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':&nbsp;{'apple':&nbsp;{},&nbsp;'grape':&nbsp;{},&nbsp;'pineapple':&nbsp;{}},&nbsp;'vehicle':&nbsp;{'car':&nbsp;{'sedan':&nbsp;{'mini&nbsp;sedan':&nbsp;{}}}}}解释这个想法:是可变的。dictworking_dict是所有 s 的参考表。"id"如果没有这样的ID,请注册。{}并注册没有字段的元素,作为根元素进入.idresult_dict附加如果不想使用 ,则只能使用 。但它更冗长。collections.defaultdictdict.setdefaultworking_dict = {}result_dict = {}for item in nested_list:&nbsp; &nbsp; name = item['name']&nbsp; &nbsp; if 'id' in item:&nbsp; &nbsp; &nbsp; &nbsp; id_ = item['id']&nbsp; &nbsp; &nbsp; &nbsp; working_dict.setdefault(id_, {}).setdefault(name, working_dict.setdefault(name, {}))&nbsp; &nbsp; else:&nbsp; &nbsp; &nbsp; &nbsp; result_dict[name] = working_dict.setdefault(name, {})print(result_dict)

湖上湖

您也可以使用递归函数手动执行此操作。理念:循环访问输入列表中的元素忽略不带键的元素id对于带有 in 键的元素:id在输出中递归搜索此键添加 元素(如果元素已经存在,则元素将添加到递归函数中,否则在之后)。# Recursive searchdef iterdictAdd(d, id, name):&nbsp; &nbsp; # For all element in the dict&nbsp; &nbsp; for k, v in d.items():&nbsp; &nbsp; &nbsp; &nbsp; # If key match -> add&nbsp; &nbsp; &nbsp; &nbsp; if k == id:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; d[id] = {**d[id], **{name: {}}}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return True&nbsp; &nbsp; &nbsp; &nbsp; else:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Recursive call&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if isinstance(v, dict):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if iterdictAdd(v, id, name):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return True&nbsp; &nbsp; return Falseout = {}# Iterate all dictfor dict_ in nested_list:&nbsp; &nbsp; # Ignore elements without "id"&nbsp;&nbsp; &nbsp; if "id" in dict_:&nbsp; &nbsp; &nbsp; &nbsp; # Search and add this key&nbsp; &nbsp; &nbsp; &nbsp; if not iterdictAdd(out, dict_["id"], dict_["name"]):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; out[dict_["id"]] = {dict_["name"]: {}}print(out)# {'fruit': {#&nbsp; &nbsp; &nbsp;'apple': {},#&nbsp; &nbsp; &nbsp;'grape': {},#&nbsp; &nbsp; &nbsp;'pineapple': {}# },#&nbsp; 'vehicle': {#&nbsp; &nbsp; &nbsp;'car': {#&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;'sedan': {}#&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}#&nbsp; &nbsp; &nbsp;}# }
随时随地看视频慕课网APP

相关分类

Python
我要回答