Python如何将扁平父子关系字典转换为层级嵌套树结构
解决方案
核心逻辑分三步:先递归提取所有嵌套层级的节点建立索引,再自动识别根节点,最后按父子关系重新挂载节点,支持任意层级嵌套、多父节点场景。
实现思路
- 递归遍历原始结构所有层级的节点,把所有
child对象提取到以节点name为键的映射表中,统一初始化空的children列表,对嵌套在父节点下、未显式标注parents的子节点,自动补全父节点为外层节点 - 遍历所有节点的
parents字段(自动拆分逗号分隔的多父节点值),统计所有被引用过的父节点名称,没有出现在父节点集合中的节点即为根节点 - 遍历所有非根节点,按其
parents配置,将节点包装为要求的{'child': 节点对象}格式,挂载到对应父节点的children列表下 - 最终将根节点包装为标准输出结构返回
完整代码
def build_hierarchical_tree(raw_data): node_index = {} # 递归提取所有层级的节点 def traverse(node_list, implicit_parent=None): for entry in node_list: current_node = entry["child"].copy() node_name = current_node["name"] # 补全隐式父节点 if "parents" not in current_node and implicit_parent is not None: current_node["parents"] = implicit_parent current_node["children"] = [] node_index[node_name] = current_node # 递归处理当前节点下嵌套的子节点 if "children" in entry["child"]: traverse(entry["child"]["children"], implicit_parent=node_name) traverse(raw_data["children"]) # 识别所有被引用的父节点,找根节点 referenced_parents = set() for node in node_index.values(): if "parents" in node: parent_list = [p.strip() for p in node["parents"].split(",")] referenced_parents.update(parent_list) root_nodes = [name for name in node_index if name not in referenced_parents] # 按父子关系挂载节点 for node_name, node in node_index.items(): if "parents" not in node: continue parent_list = [p.strip() for p in node["parents"].split(",")] for parent_name in parent_list: node_index[parent_name]["children"].append({"child": node}) # 组装最终结构 return {"children": [{"child": node_index[root]} for root in root_nodes]}
使用方法
传入原始字典即可得到结构化的树状字典,传入节点名称就能直接从返回结果中索引到对应节点,查询其所有子节点:
# 原始输入 raw_dict = {'children': [{'child': {'name': 'chi1', 'parents': 'par', 'foo1': 'bar1'}}, {'child': {'name': 'chi2', 'parents': 'par', 'foo7': 'bar7'}}, {'child': {'name': 'chi1_chi1', 'parents': 'chi1', 'foo2': 'bar2', 'children': [{'child': {'name': 'chi1_chi1_chil1', 'foo3': 'bar3'}}, {'child': {'name': 'chi1_chi1_chi2', 'foo4': 'bar4'}}]}}, {'child': {'name': 'par', 'foo5': 'bar5'}}, {'child': {'name': 'chi1_chi2', 'parents': 'chi1, chi2', 'foo6': 'bar6'}}]} tree = build_hierarchical_tree(raw_dict) # 示例:查询指定名称节点的所有子节点 def get_node_by_name(tree, target_name): def search(node_list): for entry in node_list: child = entry["child"] if child["name"] == target_name: return child res = search(child["children"]) if res: return res return None return search(tree["children"]) par_node = get_node_by_name(tree, "par") print(par_node["children"]) # 输出par下所有直属子节点
注意事项
- 代码会完整保留节点上的所有自定义属性(如示例中的
foo1/bar1等字段),不会做额外修改 - 自动支持多父节点场景,逗号分隔的父节点配置会被正确识别,节点会挂载到所有对应父节点下
- 支持任意深度的嵌套结构,不需要提前配置层级数
- 给出的预期结果中存在笔误,将原始节点名
chi1_chi1_chil1写为了chi1_chi1_chi1,代码会保留原始输入的节点名称,不会擅自篡改
内容的提问来源于stack exchange,提问作者Slayer
相关产品推荐
相关产品推荐

