Python 将字典列表转换为嵌套字典列表

Python 将字典列表转换为嵌套字典列表,python,python-2.7,dictionary,data-structures,Python,Python 2.7,Dictionary,Data Structures,我尝试并看到了上述问题的多种解决方案,但未能找到适合我情况的解决方案。 我有下列词典 input_list = [ {'k0':'v0','level':0,'row':0}, {'k1':'v1','level':1,'row':1}, {'k2':'v2','level':2,'row':2}, {'k3':'v3','level':2,'row':3},

我尝试并看到了上述问题的多种解决方案,但未能找到适合我情况的解决方案。 我有下列词典

input_list = [
                {'k0':'v0','level':0,'row':0},
                {'k1':'v1','level':1,'row':1},
                {'k2':'v2','level':2,'row':2},
                {'k3':'v3','level':2,'row':3},
                {'k4':'v4','level':1,'row':4},
                {'k5':'v5','level':2,'row':5},
                {'k6':'v6','level':1,'row':6},
                {'k7':'v7','level':0,'row':7},
                {'k8':'v8','level':1,'row':8},
                {'k9':'v9','level':2,'row':9},
            ]
我需要用以下方式将这个列表转换为嵌套字典列表

[
  {'k0':'v0',
   'level':0,
   'child':[
          {'k1':'v1','level':1,'child':[{'k2':'v2','level':2}, 
                                        {'k3':'v3','level':2}]},
          {'k4':'v4','level':1,'child':[{'k5':'v5','level':2}]},
          {'k6':'v6','level':1}
         ]},

  {'k7':'v7',
   'level':0,
   'child':[{'k8':'v8','level':1,'child':[{'k9':'v9','level':2}]}]}
]
我尝试的解决方案如下

levels = dict()
for n in input_list:
    levels.setdefault(n['level'], []).append(n)

这使我的字典与水平分开,但我无法移动过去的代码,我想要的解决方案


任何帮助都将不胜感激。谢谢

您可以将递归与
itertools.groupby一起使用:

from itertools import groupby as gb
data = [{'k0': 'v0', 'level': 0, 'row': 0}, {'k1': 'v1', 'level': 1, 'row': 1}, {'k2': 'v2', 'level': 2, 'row': 2}, {'k3': 'v3', 'level': 2, 'row': 3}, {'k4': 'v4', 'level': 1, 'row': 4}, {'k5': 'v5', 'level': 2, 'row': 5}, {'k6': 'v6', 'level': 1, 'row': 6}, {'k7': 'v7', 'level': 0, 'row': 7}, {'k8': 'v8', 'level': 1, 'row': 8}, {'k9': 'v9', 'level': 2, 'row': 9}]
_d = [{a:b for a, b in i.items() if a not in {'row'}} for i in data]

def get_results(d, l = 0):
  r, p = [(a, list(b)) for a, b in gb(d, key=lambda x:x['level'] == l)], []
  for a, b in r:
     if a:
        p.extend(b)
     else:      
        p[-1]['child'] = get_results(b, l+1)
  return p

输出:

[
  {
    "k0": "v0",
    "level": 0,
    "child": [
        {
            "k1": "v1",
            "level": 1,
            "child": [
                {
                    "k2": "v2",
                    "level": 2
                },
                {
                    "k3": "v3",
                    "level": 2
                }
            ]
        },
        {
            "k4": "v4",
            "level": 1,
            "child": [
                {
                    "k5": "v5",
                    "level": 2
                }
            ]
        },
        {
            "k6": "v6",
            "level": 1
        }
    ]
 },
 {
    "k7": "v7",
    "level": 0,
    "child": [
        {
            "k8": "v8",
            "level": 1,
            "child": [
                {
                    "k9": "v9",
                    "level": 2
                }
            ]
         }
      ]
    }
]
#该命令存储按级别查看的最后一条命令
dict_by_levels=[None]*len(输入_列表)
#归还;从第一个“根”开始
输出列表=[输入列表[0]]
对于zip中的上一个目录、当前目录(输入列表,输入列表[1:]):
#获取上一级和当前级,并将它们存储在levels dict中
上一级,当前级=上一级[“级别”],当前级[“级别”]
逐级记录[上一级]=上一级记录
逐级记录[当前记录]=当前记录
#如果我们目前处于更深的层次,请附加到上一个dict的子级
如果当前级别>上一级别:
prev_dict.setdefault(“child”,[]).append(cur_dict)
#如果我们目前处于较浅或相等的水位*且*当前水位不是0,
#然后获得目前为止看到的dict之前的最后一个级别,并附加到它
elif cur_level 0),那么我们只需附加到当前dict的子级

如果当前级别小于等于上一级别,这意味着我们应该将级别
当前级别-1
(这里的
dict by_levels
帮助)附加到上次看到的dict的子级。当然,如果当前级别为
0
,我们不会这样做-我们有一个新的根


根案例在
else
子句中通过追加到要返回的输出列表来处理。

请用您尝试过的代码更新您的问题。“找不到解决方案”-你有没有试着提出一个解决方案?我建议你先用文字写下你用来决定如何处理输入列表中的每个dict的规则。好奇:是什么原因让你需要超复杂的嵌套字典结构?你需要在字符串周围加引号感谢你的回答,因为它无法捕获水平仪2@KetanPujare如果有一组子级有自己的子级,代码最初会将多个子级压缩为一个
dict
。但是,请参阅我最近的编辑,因为我添加了一个与您所需输出匹配的变通方法。
[
  {
    "k0": "v0",
    "level": 0,
    "child": [
        {
            "k1": "v1",
            "level": 1,
            "child": [
                {
                    "k2": "v2",
                    "level": 2
                },
                {
                    "k3": "v3",
                    "level": 2
                }
            ]
        },
        {
            "k4": "v4",
            "level": 1,
            "child": [
                {
                    "k5": "v5",
                    "level": 2
                }
            ]
        },
        {
            "k6": "v6",
            "level": 1
        }
    ]
 },
 {
    "k7": "v7",
    "level": 0,
    "child": [
        {
            "k8": "v8",
            "level": 1,
            "child": [
                {
                    "k9": "v9",
                    "level": 2
                }
            ]
         }
      ]
    }
]
# This stores last dicts seen by their levels
dict_by_levels = [None] * len(input_list)

# To be returned; begins with the first "root"
output_list = [input_list[0]]

for prev_dict, cur_dict in zip(input_list, input_list[1:]):
    # Get previous and current level, and store them in levels dict
    prev_level, cur_level = prev_dict["level"], cur_dict["level"]
    dict_by_levels[prev_level] = prev_dict
    dict_by_levels[cur_level] = cur_dict

    # If we are currently in a deeper level, append to previous dict's child
    if cur_level > prev_level:
        prev_dict.setdefault("child", []).append(cur_dict) 

    # If we are currently in a shallower or equal level *and* the current level is not 0,
    # then get the last one-level-before dict seen so far, and append to it
    elif cur_level <= prev_level and cur_level != 0:
        dict_by_levels[cur_level-1].setdefault("child", []).append(cur_dict)

    # This else is equivalent to "if cur_level == 0" i.e. a "root" dict
    else:
        output_list.append(cur_dict)