递归构建分层JSON树?

2024-03-28 22:39:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个亲子关系数据库。数据看起来如下,但可以以任何方式显示(字典、列表列表、JSON等)。

links=(("Tom","Dick"),("Dick","Harry"),("Tom","Larry"),("Bob","Leroy"),("Bob","Earl"))

我需要的输出是一个层次JSON树,它将用d3呈现。数据中有离散的子树,我会将其附加到根节点。所以我需要递归地遍历链接,并构建树结构。我能做的最多的就是遍历所有人并附加他们的孩子,但是我不知道要做更高阶的链接(例如,如何将一个有孩子的人附加到其他人的孩子上)。这类似于另一个问题here,但我无法提前知道根节点,因此无法实现接受的解决方案。

我将从我的示例数据中获取以下树结构。

{
"name":"Root",
"children":[
    {
     "name":"Tom",
     "children":[
         {
         "name":"Dick",
         "children":[
             {"name":"Harry"}
         ]
         },
         {
          "name":"Larry"}
     ]
    },
    {
    "name":"Bob",
    "children":[
        {
        "name":"Leroy"
        },
        {
        "name":"Earl"
        }
    ]
    }
]
}

这个结构在我的d3布局中呈现出这样的效果。Rendered image


Tags: 数据namejson列表节点孩子bobd3
3条回答

要标识根注释,可以解压缩links,并查找不是子级的父级:

parents, children = zip(*links)
root_nodes = {x for x in parents if x not in children}

然后可以应用递归方法:

import json

links = [("Tom","Dick"),("Dick","Harry"),("Tom","Larry"),("Bob","Leroy"),("Bob","Earl")]
parents, children = zip(*links)
root_nodes = {x for x in parents if x not in children}
for node in root_nodes:
    links.append(('Root', node))

def get_nodes(node):
    d = {}
    d['name'] = node
    children = get_children(node)
    if children:
        d['children'] = [get_nodes(child) for child in children]
    return d

def get_children(node):
    return [x[1] for x in links if x[0] == node]

tree = get_nodes('Root')
print json.dumps(tree, indent=4)

我使用一个集合来获取根节点,但是如果顺序很重要,可以使用列表和remove the duplicates

如果要将数据格式化为HTML/JS本身的层次结构,请查看:

Generate (multilevel) flare.json data format from flat json

如果您有大量的数据,那么Web转换将更快,因为它使用reduce功能,而Python缺少功能性编程。

顺便说一句:我也在研究同一个主题,即在d3.js中生成可折叠的树结构。如果你想合作,我的电子邮件是:erprateek.vit@gmail.com。

尝试遵循代码:

import json

links = (("Tom","Dick"),("Dick","Harry"),("Tom","Larry"),("Tom","Hurbert"),("Tom","Neil"),("Bob","Leroy"),("Bob","Earl"),("Tom","Reginald"))

name_to_node = {}
root = {'name': 'Root', 'children': []}
for parent, child in links:
    parent_node = name_to_node.get(parent)
    if not parent_node:
        name_to_node[parent] = parent_node = {'name': parent}
        root['children'].append(parent_node)
    name_to_node[child] = child_node = {'name': child}
    parent_node.setdefault('children', []).append(child_node)

print json.dumps(root, indent=4)

相关问题 更多 >