Python递归函数生成Treant JS树形结构遇层级问题求助
Fixing Recursive Tree Generation for Treant JS JSON Format
我看了你的代码和遇到的问题,核心问题在于递归过程中没有正确将子节点挂载到对应的父节点上,反而都加到了根节点的children数组里。另外,你用了可变默认参数output={},这在Python里是个常见陷阱——可变默认参数只会初始化一次,多次调用时会保留之前的状态,导致数据混乱。
下面是修正后的方案,思路是先预处理数据构建快速查找的映射,再通过递归函数逐个构建节点及其子节点:
Step 1: 预处理数据提高效率
先把原始记录转换成字典和父节点映射表,避免每次查找子节点都遍历整个列表:
def get_records(): # ID, Tree ID, Metric Name, Metric Description, Metric Formula, Parent, ReferenceID records = ( ('1', '1', 'metric 1', 'desc', 'form * x - y', '', 'metric_1'), ('2', '1', 'metric 2', 'desc', 'form * x - y', 'metric_1', 'metric_2'), ('3', '1', 'metric 3', 'desc', 'form * x - y', 'metric_1', 'metric_3'), ('4', '1', 'metric 4', 'desc', 'form * x - y', 'metric_2', 'metric_4'), ('5', '1', 'metric 5', 'desc', 'form * x - y', 'metric_2', 'metric_5') ) # 用refid作为key存储每条记录 record_dict = {rec[6]: rec for rec in records} # 构建父节点到子节点refid的映射 parent_map = {} for rec in records: parent_ref = rec[5] child_ref = rec[6] if parent_ref not in parent_map: parent_map[parent_ref] = [] parent_map[parent_ref].append(child_ref) return record_dict, parent_map
Step 2: 递归构建树形结构
写一个递归函数,负责构建单个节点及其所有子节点,确保子节点正确挂载到父节点的children数组中:
def build_tree(refid, record_dict, parent_map): # 获取当前节点的记录 rec = record_dict[refid] # 创建当前节点的基础结构,匹配Treant要求的格式 node = { refid: { 'name': rec[2], 'desc': rec[3], 'contact': rec[4] } } # 查找当前节点的所有子节点refid child_refs = parent_map.get(refid, []) if child_refs: # 递归构建每个子节点,添加到当前节点的children数组 node['children'] = [build_tree(child_ref, record_dict, parent_map) for child_ref in child_refs] return node
Step 3: 生成最终输出
在主函数中找到根节点(parent为空的记录),调用递归函数生成完整树形结构:
if __name__ == '__main__': record_dict, parent_map = get_records() # 找到根节点(parent字段为空的记录) root_refid = next(refid for refid, rec in record_dict.items() if rec[5] == '') # 生成符合要求的树形结构 output = build_tree(root_refid, record_dict, parent_map) # 格式化输出查看结果 import json print(json.dumps(output, indent=2))
最终输出结果
运行后会得到完全符合Treant JS要求的结构:
{ "metric_1": { "name": "metric 1", "desc": "desc", "contact": "form * x - y" }, "children": [ { "metric_2": { "name": "metric 2", "desc": "desc", "contact": "form * x - y" }, "children": [ { "metric_4": { "name": "metric 4", "desc": "desc", "contact": "form * x - y" } }, { "metric_5": { "name": "metric 5", "desc": "desc", "contact": "form * x - y" } } ] }, { "metric_3": { "name": "metric 3", "desc": "desc", "contact": "form * x - y" } } ] }
原代码问题解析
- 可变默认参数陷阱:
generate_output(record, output={})中的output只会初始化一次,多次调用会复用同一个字典,导致数据混乱。 - 层级追踪错误:嵌套的
generate函数直接操作外层的output,没有区分当前节点的层级,所有子节点都被加到了根节点的children里。 - 低效的子节点查找:每次调用
find_children都重新遍历整个记录列表,不仅效率低,也没有和当前节点的结构关联起来。
内容的提问来源于stack exchange,提问作者F. Leone
相关产品推荐
相关产品推荐

