从深层遍历嵌套字典并按依赖逐层向上删除id的需求
问题描述
我有一个由报告生成的嵌套字典(结构可能变化),需要完成以下操作:
- 从字典的最深层开始,找到其中的
id字段(示例中如'id': u'ef3c8cf1-0987-4e56-a6d5-763c42be1f75',可能存在多个) - 删除该
id后将剩余内容上移一层,重复此操作直至删除顶层id - 由于存在依赖关系,需先删除孤立的
id,再逐层向上处理
字典示例
{ 'id': u'4c31d813-a989-47dd-b01b-9a27b8db2dfc', 'snapshots': [ { 'id': u'3ddc7ddd-02ca-4669-a0cb-fb0d56a4a6f5', 'volumes': [ { 'id': u'5488de90-50dc-4d72-a6aa-c995422fa179', 'snapshots': [], 'snapshot_id': u'3ddc7ddd-02ca-4669-a0cb-fb0d56a4a6f5' }, { 'id': u'e566645f-4fb3-4778-be67-447a5bdd678d', 'snapshots': [ { 'id': u'd637f6ea-4a41-448c-874f-ffe624ddc597', 'volumes': [ { 'id': u'ef3c8cf1-0987-4e56-a6d5-763c42be1f75', 'snapshots': [], 'snapshot_id': u'd637f6ea-4a41-448c-874f-ffe624ddc597' } ] } ], 'snapshot_id': u'3ddc7ddd-02ca-4669-a0cb-fb0d56a4a6f5' }, { 'id': u'196483ee-4f21-4d83-8e15-8caea532b2ab', 'snapshots': [], 'snapshot_id': u'3ddc7ddd-02ca-4669-a0cb-fb0d56a4a6f5' } ] } ], 'snapshot_id': None }
相关Python代码
oh=openstack_helper.OpenstackHelper() def get_objects(item): items=None if item == 'stacks': items=oh.get_stacks() if item == 'volumes': items=oh.get_volumes() if item == 'snapshots': items=oh.get_snapshots() return items def dep_graph(volumes,snapshots,snapshot_id=None): vol_list=[] for volume in volumes: if volume.snapshot_id == snapshot_id: info={'id':volume.id,'snapshot_id':volume.snapshot_id,'snapshots':[], } vol_list.append(info) for snapshot in snapshots: for volume in vol_list: snap_list=[] if snapshot.volume_id == volume['id']: info={'id':snapshot.id, 'volumes':[]} info['volumes'].extend(dep_graph(volumes,snapshots,snapshot.id)) volume['snapshots'].append(info) return vol_list if __name__ == '__main__': volumes = get_objects('volumes') snapshots = get_objects('snapshots') output = dep_graph(volumes, snapshots) print output
解决方案
要实现从最深层开始删id并把剩余内容上移的需求,咱们可以用**深度优先遍历(DFS)**的思路——先钻到最内层的节点处理完,再一步步往外走,这样刚好符合先删孤立id、再逐层向上处理的要求。
下面是具体的实现代码:
def remove_ids_recursive(data): # 如果是列表,递归处理每个元素 if isinstance(data, list): return [remove_ids_recursive(item) for item in data] # 如果是字典,先递归处理所有值,再删除id并重组 elif isinstance(data, dict): # 先处理所有子节点(深度优先,确保先处理最深层) processed_data = {k: remove_ids_recursive(v) for k, v in data.items()} # 删除id字段 if 'id' in processed_data: del processed_data['id'] return processed_data # 非字典非列表,直接返回 else: return data # 测试示例字典 sample_dict = { 'id': u'4c31d813-a989-47dd-b01b-9a27b8db2dfc', 'snapshots': [ { 'id': u'3ddc7ddd-02ca-4669-a0cb-fb0d56a4a6f5', 'volumes': [ { 'id': u'5488de90-50dc-4d72-a6aa-c995422fa179', 'snapshots': [], 'snapshot_id': u'3ddc7ddd-02ca-4669-a0cb-fb0d56a4a6f5' }, { 'id': u'e566645f-4fb3-4778-be67-447a5bdd678d', 'snapshots': [ { 'id': u'd637f6ea-4a41-448c-874f-ffe624ddc597', 'volumes': [ { 'id': u'ef3c8cf1-0987-4e56-a6d5-763c42be1f75', 'snapshots': [], 'snapshot_id': u'd637f6ea-4a41-448c-874f-ffe624ddc597' } ] } ], 'snapshot_id': u'3ddc7ddd-02ca-4669-a0cb-fb0d56a4a6f5' }, { 'id': u'196483ee-4f21-4d83-8e15-8caea532b2ab', 'snapshots': [], 'snapshot_id': u'3ddc7ddd-02ca-4669-a0cb-fb0d56a4a6f5' } ] } ], 'snapshot_id': None } # 处理后的结果 result = remove_ids_recursive(sample_dict) print(result)
代码说明
- 深度优先遍历逻辑:函数会先递归处理所有子元素(比如列表里的每一项、字典里的每个值),确保最深层的节点最先被处理,完美契合先删孤立
id的要求。 - 删除
id并保留其他内容:等所有子节点都处理完后,再删掉当前字典里的id字段,剩下的键值对自然就相当于“上移”后的内容了。 - 适配可变结构:不管你的字典嵌套结构怎么变,只要是字典和列表组成的嵌套结构,这个函数都能正确处理。
你可以把这个函数集成到你的现有代码中,比如在dep_graph函数返回结果后,调用remove_ids_recursive(output)来得到最终处理后的结果。
内容的提问来源于stack exchange,提问作者Heenashree Khandelwal
相关产品推荐
相关产品推荐

