合并嵌套字典生成D3旭日图所需JSON文件的问题
如何合并深层嵌套的分类字典(用于D3旭日图)
看起来你需要的是一个递归的嵌套字典合并逻辑——核心是在每一层级找到同名同类型的节点,合并它们的子节点,而不是直接重复添加。我来帮你梳理解决方案:
问题分析
你当前的代码问题在于merge函数没有针对嵌套层级做节点匹配:它只是简单合并字典,导致同一层级的同名节点(比如"Bacteria")被重复创建,而不是找到已存在的节点并合并其子节点。
解决方案:递归合并节点
我们需要写一个递归函数,针对每个节点的children数组,根据name和tax字段匹配已存在的节点:
- 如果两个节点的
name和tax完全一致,就递归合并它们的children - 如果目标节点的
children里没有匹配的节点,就把新节点添加进去 - 对于叶子节点(带有
size字段的节点),可以选择直接追加或者累加size(根据你的需求调整)
完整代码实现
def merge_nodes(target_node, new_node): """递归合并两个嵌套的分类节点""" # 首先检查当前节点是否匹配(name和tax都一致才是同一节点) if target_node['name'] == new_node['name'] and target_node['tax'] == new_node['tax']: # 如果是叶子节点(有size字段),直接追加子节点(若需累加size可修改此处逻辑) if 'size' in new_node: target_node.setdefault('children', []).append(new_node) return target_node # 处理子节点:遍历新节点的children,尝试合并到目标节点的children中 target_children = target_node.setdefault('children', []) for new_child in new_node.get('children', []): # 寻找目标子节点中是否有匹配项 matched = False for target_child in target_children: if target_child['name'] == new_child['name'] and target_child['tax'] == new_child['tax']: merge_nodes(target_child, new_child) matched = True break # 没有匹配的就添加新子节点 if not matched: target_children.append(new_child) return target_node else: # 当前节点不匹配,直接返回新节点(调用方会处理添加逻辑) return new_node def merge_dicts(dict_list): """合并字典列表为单个嵌套字典""" if not dict_list: return {} # 初始化结果为第一个字典的深拷贝,避免修改原数据 import copy result = copy.deepcopy(dict_list[0]) # 遍历剩余字典,逐个合并到结果中 for d in dict_list[1:]: merge_nodes(result, d) return result
使用示例
假设你的字典列表是tempDicts,调用方式如下:
# 模拟你的多个小字典数据 tempDicts = [ { "name": "root", "tax": "Tax level: domain", "children": [ { "name": "Bacteria", "tax": "Tax level: Kingdom", "children": [ { "name": "Firmicutes", "tax": "Tax level: Phylum", "children": [ { "name": "Bacillidae", "tax": "Tax level: Class", "children": [ { "name": "Bacillinae", "tax": "Tax level: Order", "children": [ { "name": "Bacillini", "tax": "Tax level: Family", "children": [ { "name": "Bacillus", "tax": "Tax level: Genus", "children": [ { "name": "", "size": 5, "tax": "Tax level: Species" } ] } ] } ] } ] } ] } ] }, { "name": "root", "tax": "Tax level: domain", "children": [ { "name": "Bacteria", "tax": "Tax level: Kingdom", "children": [ { "name": "Firmicutes", "tax": "Tax level: Phylum", "children": [ { "name": "Firmicutes", "tax": "Tax level: Class", "children": [ { "name": "Tissierellia", "tax": "Tax level: Order", "children": [ { "name": "unclassified Tissierellia", "tax": "Tax level: Family", "children": [ { "name": "Tepidimicrobium", "tax": "Tax level: Genus", "children": [ { "name": "", "size": 5, "tax": "Tax level: Species" } ] } ] } ] } ] } ] } ] }, { "name": "root", "tax": "Tax level: domain", "children": [ { "name": "Thermotogae", "tax": "Tax level: Phylum", "children": [ { "name": "Thermotogae", "tax": "Tax level: Class", "children": [ { "name": "Thermotogales", "tax": "Tax level: Order", "children": [ { "name": "Thermotogaceae", "tax": "Tax level: Family", "children": [ { "name": "Thermotoga", "tax": "Tax level: Genus", "children": [ { "name": "", "size": 5, "tax": "Tax level: Species" } ] } ] } ] } ] } ] } ] } ] # 执行合并 merged_result = merge_dicts(tempDicts) # 格式化输出结果(方便查看) import json print(json.dumps(merged_result, indent=2))
代码说明
merge_nodes函数:核心递归逻辑,负责匹配并合并单个节点及其子节点,确保相同层级的同名节点不会重复创建。merge_dicts函数:处理整个字典列表,从第一个字典开始,依次合并后续的每个字典到结果中,避免了原代码中容易出现的索引越界问题。- 叶子节点处理:示例中是直接追加叶子节点(相同species的节点会并列),如果需要累加
size,可以修改叶子节点的处理逻辑,比如找到同名的叶子节点后累加size而不是追加。
内容的提问来源于stack exchange,提问作者Shane P
相关产品推荐
相关产品推荐

