如何将字典列表转换成树形如Nest字典?

时间:2019-04-12 23:36:26

标签: python python-3.x dictionary

我的数据以这种格式-

data = {
    "label": "xyz.com",
    "children": [
        {
            "parent": "abc.com",
            "label": "user-3",
            "depth": 1
        },
        {

            "parent": "xyz.com",
            "label": "abc.com",
            "depth": 0
        },
        {

            "parent": "xyz.com",
            "label": "user-1",
            "depth": 0
        }
    ]
}

我想生成一个看起来像这样的结果(嵌套词典)-

result = {
    "label": "xyz.com",
    "children": [
         {

             "parent": "xyz.com",
             "label": "user-1",
             "depth": 0
         },
        {

            "parent": "xyz.com",
            "label": "abc.com",
            "depth": 0,
            "children": [
                {
                    "parent": "abc.com",
                    "label": "user-3",
                    "depth": 1
                }
            ]
         }

    ]
}

使用标签-父级深度将初始词典转换为嵌套词典。

此外,可能有任何数量的孩子。例如-

result = {
    "lable": "xyz.com",
    "children": [
         {
             "parent": "xyz.com",
             "label": "user-1",
             "depth": 0
         },
        {

            "parent": "xyz.com",
            "label": "abc.com",
            "depth": 0,
            "children": [
                {
                    "parent": "abc.com",
                    "label": "user-3",
                    "depth": 1,
                    "children": [
                        {...}, {...}
                    ]
                }
            ]
         }
    ]
}

不确定递归是否可行,或者是否有其他解决方案。

感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

一种更有效,单次通过的线性方法是构建一个将标签映射到节点的字典,这样,您只需在字典中查找父节点的标签,然后将节点附加到节点即可轻松获得父节点。父节点的Json$JsonTextNode子列表。如果迭代早于其父节点到达子节点,请先使用children为父节点初始化dict条目,以便父节点以后可以使用预先存在的dict.setdefault条目更新自身:

children

result = {'label': data['label']} nodes = {data['label']: result} for node in data['children']: node.update(nodes.get(node['label'], {})) nodes[node['label']] = node nodes.setdefault(node['parent'], {}).setdefault('children', []).append(node) 变为:

result

答案 1 :(得分:0)

您可以使用递归:

data = {'label': 'xyz.com', 'children': [{'parent': 'abc.com', 'label': 'user-3', 'depth': 1}, {'parent': 'xyz.com', 'label': 'abc.com', 'depth': 0}, {'parent': 'xyz.com', 'label': 'user-1', 'depth': 0}]}
def group(d):
  new_d = [i for i in d if all(c.get('label') != i.get('parent') for c in d)]
  c = [(lambda x:{a:b for a, b in x.items() if a != 'children' or b})({**i, 'children':[*i.get('children', []), *[j for j in d if j.get('parent') == i['label']]]}) for i in new_d]
  return [i if 'children' not in i else {**i, 'children':group(i['children'])} for i in c]

import json
print(json.dumps(group([data]), indent=4))

输出:

[
  {
    "label": "xyz.com",
    "children": [
        {
            "parent": "xyz.com",
            "label": "abc.com",
            "depth": 0,
            "children": [
                {
                    "parent": "abc.com",
                    "label": "user-3",
                    "depth": 1
                }
            ]
        },
        {
            "parent": "xyz.com",
            "label": "user-1",
            "depth": 0
        }
      ]
   }
]

答案 2 :(得分:0)

一种更简单的递归方法实现是利用字典中已有的键并对字典进行突变,而不是创建新的:

def convert(nodes, parent):
    children = [convert(nodes, node) for node in nodes if node['parent'] == parent['label']]
    if children:
        parent['children'] = children
    return parent

使convert(data.pop('children'), data)返回:

{'label': 'xyz.com',
 'children': [{'parent': 'xyz.com',
               'label': 'abc.com',
               'depth': 0,
               'children': [{'parent': 'abc.com',
                             'label': 'user-3',
                             'depth': 1}]},
              {'parent': 'xyz.com', 'label': 'user-1', 'depth': 0}]}