递归构建分层JSON树?
Posted
技术标签:
【中文标题】递归构建分层JSON树?【英文标题】:Recursively build hierarchical JSON tree? 【发布时间】:2013-08-04 05:02:51 【问题描述】:我有一个父子连接数据库。数据如下所示,但可以以任何您想要的方式呈现(字典、列表列表、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 布局中呈现如下。
【问题讨论】:
【参考方案1】:尝试以下代码:
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)
【讨论】:
有点皱纹....您的代码在使用更多链接时无法按预期工作:例如,当我尝试使用这些链接时,Tom 多次出现!链接=((“汤姆”,“迪克”),(“迪克”,“哈利”),(“汤姆”,“拉里”),(“汤姆”,“赫伯特”),(“汤姆”,“尼尔"),("鲍勃","勒罗伊"),("鲍勃","厄尔"),("汤姆","雷金纳德"))【参考方案2】:如果您想在 html/JS 本身中将数据格式化为层次结构,请查看:
Generate (multilevel) flare.json data format from flat json
如果您有大量数据,Web 转换会更快,因为它使用 reduce 功能,而 Python 缺乏函数式编程。
顺便说一句:我也在研究同一主题,即在 d3.js 中生成可折叠的树结构。如果你想一起工作,我的电子邮件是:erprateek.vit@gmail.com。
【讨论】:
【参考方案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。
【讨论】:
以上是关于递归构建分层JSON树?的主要内容,如果未能解决你的问题,请参考以下文章
Windows 窗体 TreeView - 绑定分层递归数据源