将节点列表转换为 python 中的嵌套字典

Transforming a list of nodes in to a nested dict in python

我在 python 中有一个代表邻接列表的字典列表,我想将此列表转换为嵌套的 python 字典。使用 namechildren 键。

节点列表

这是一个字典列表的例子,它们是列表的前 10 个元素。原始包含1000个元素。

[{'id': 1, 'name': 'External sector', 'parent_id': 0},
 {'id': 3, 'name': 'Capital and financial markets', 'parent_id': 0},
 {'id': 77, 'name': 'Credit indicators', 'parent_id': 0},
 {'id': 15, 'name': 'Economic activity', 'parent_id': 0},
 {'id': 17, 'name': 'Monetary indicators', 'parent_id': 0},
 {'id': 30, 'name': 'Regional economy', 'parent_id': 0},
 {'id': 114, 'name': 'International economy', 'parent_id': 0},
 {'id': 157, 'name': 'National private financial system', 'parent_id': 0},
 {'id': 176, 'name': 'Financial Stability', 'parent_id': 0},
 {'id': 222, 'name': 'Financial Inclusion', 'parent_id': 0}]

我试过的

我在 SO 中找到了这个函数,它能够将这个字典列表转换为嵌套的 python 字典:

def list_to_tree(data):
    out = { 
#         0: { 'id': 0, 'parent_id': 0, 'name': "Root node", 'sub': [] }
    }

    for p in data:
        out.setdefault(p['parent_id'], { 'sub': [] })
        out.setdefault(p['id'], { 'sub': [] })
        out[p['id']].update(p)
        out[p['parent_id']]['sub'].append(out[p['id']])

    return out[0]

此函数以这种方式生成字典:

{'id': 0,
 'name': 'rootnode',
 'parent_id': None,
 'sub': [{'id': 1,
          'name': 'External sector',
          'parent_id': 0,
          'sub': [{'id': 2,
                   'name': 'Exchange rates',
                   'parent_id': 1,
                   'sub': [{'id': 242,
                            'name': 'Controlled or free rates',
                            'parent_id': 2,
                            'sub': []},
                           {'id': 243,
                            'name': 'Floating rates',
                            'parent_id': 2,
                            'sub': []},
                           {'id': 532,
                            'name': 'Real and effective exchange rate indices',
                            'parent_id': 2,
                            'sub': []},
                           {'id': 533,
                            'name': 'Foreign exchange and wage indicators',
                            'parent_id': 2,
                            'sub': []},
                           {'id': 548,
                            'name': 'Average of period',
                            'parent_id': 2,
                            'sub': []},

但我想以这种方式生成没有 id 的字典

{
 'name': 'rootnode',
 'children': [{
          'name': 'External sector',
          'children': [{
                   'name': 'Exchange rates',
                   'children': [{
                            'name': 'Controlled or free rates',
                            'children': []},
                           {
                            'name': 'Floating rates',
                            'children': []},
                           {
                            'name': 'Real and effective exchange rate indices',
                            'children': []},
                           {
                            'name': 'Foreign exchange and wage indicators',
                            'children': []},
                           {
                            'name': 'Average of period',
                            'children': []},

有什么方法可以更改我发现的这个函数以产生所需的输出吗? 任何提示、提示或建议都非常受欢迎。

您可以稍微修改一下函数:

  • 使用 'children' 键代替 'sub'
  • 仅使用您想要的键(名称和子节点)初始化根节点
  • 而不是调用 .update(复制 所有 键),只分配 'name' 键
def list_to_tree(data):
    out = { 
        0: { 'name': 'rootnode', 'children': [] }
    }

    for p in data:
        out.setdefault(p['parent_id'], { 'children': [] })
        out.setdefault(p['id'], { 'children': [] })
        out[p['id']]['name'] = p['name']
        out[p['parent_id']]['children'].append(out[p['id']])

    return out[0]

将字典列表(邻接 id-parent 和其他键)转换为嵌套字典(id、children[]、其他键...

def nested_tree(data, id='id', parent='parent', children='children', 
root=None, delete_parent=True):
    nodes = list(filter(lambda item: item[parent] == root, data))
    def get_children(node):
        nested = []
        for item in list(filter(lambda item: item[parent] == node[id], data)):
            item[children] = get_children(item)
            if delete_parent:
                nested.append((lambda parent, **kw: kw)(**item))
            else:
                nested.append(item)
        return nested

    for node in nodes:
        node[children] = get_children(node)
        if delete_parent:
            del node[parent]
    return nodes