Python嵌套字典列表按shotType和has_children过滤返回空列表排查
嵌套字典列表筛选问题
我有一组嵌套字典列表,需要筛选出包含shotType为shot且has_children为True的节点的完整层级结构。自行编写了递归函数filter_data,但执行后返回空列表,无法得到预期的嵌套结构结果。
测试数据
data = [ { 'name': 'wdw show', 'id': '12345', 'parentId': None, 'jobType': 'job', 'has_children': True, 'children': [ { 'name': 'wdw Scene1', 'id': '123456', 'parentId': '12345', 'sceneType': 'scene', 'has_children': True, 'children': [ { 'name': 'wdw shot1', 'id': '23456', 'parentId': '123456', 'shotType': 'shot', 'has_children': True, 'children': [ { 'name': 'wdw task1', 'id': '0987', 'parentId': '23456', 'taskType': 'task', 'has_children': False, 'children': [] } ] }, { 'name': 'wdw shot2', 'id': '23457', 'parentId': '123456', 'shotType': 'shot', 'has_children': True, 'children': [ { 'name': 'wdw task2', 'id': '0986', 'parentId': '23457', 'taskType': 'task', 'has_children': False, 'children': [] } ] } ] }, { 'name': 'wdw Scene2', 'id': '123457', 'parentId': '12345', 'sceneType': 'scene', 'has_children': True, 'children': [ { 'name': 'wdw shot3', 'id': '3456', 'parentId': '123457', 'shotType': 'shot', 'has_children': False, 'children': [] }, { 'name': 'wdw shot4', 'id': '3457', 'parentId': '123457', 'shotType': 'shot', 'has_children': False, 'children': [] } ] }, { 'name': 'wdw Scene3', 'id': '123458', 'parentId': '12345', 'sceneType': 'scene', 'has_children': True, 'children': [ { 'name': 'wdw shot5', 'id': '456', 'parentId': '123458', 'shotType': 'shot', 'has_children': False, 'children': [] }, { 'name': 'wdw shot6', 'id': '457', 'parentId': '123458', 'shotType': 'shot', 'has_children': False, 'children': [] } ] } ] } ]
期望输出
Expected_data = [ { 'name': 'wdw show', 'id': '12345', 'parentId': None, 'jobType': 'job', 'has_children': True, 'children': [ { 'name': 'wdw Scene1', 'id': '123456', 'parentId': '12345', 'sceneType': 'scene', 'has_children': True, 'children': [ { 'name': 'wdw shot1', 'id': '23456', 'parentId': '123456', 'shotType': 'shot', 'has_children': True, 'children': [ { 'name': 'wdw task1', 'id': '0987', 'parentId': '23456', 'taskType': 'task', 'has_children': False, 'children': [] } ] }, { 'name': 'wdw shot2', 'id': '23457', 'parentId': '123456', 'shotType': 'shot', 'has_children': True, 'children': [ { 'name': 'wdw task2', 'id': '0986', 'parentId': '23457', 'taskType': 'task', 'has_children': False, 'children': [] } ] } ] } ] } ]
当前代码
def filter_data(data): filtered_data = [] for item in data: filtered_item = item.copy() children = item.get('children') if children: filtered_children = filter_data(children) if any( grandchild.get('shotType') == 'shot' and grandchild.get('has_children') for child in filtered_children for grandchild in child.get('children', []) ): filtered_item['children'].extend(filtered_children) # Append the filtered_children list filtered_data.append(filtered_item) return filtered_data expected_data = filter_data(data) print(expected_data)
问题分析
当前代码存在三个核心问题:
- 筛选逻辑颠倒:只检查过滤后的子节点的孙节点是否符合条件,忽略了当前节点本身或直接子节点符合条件的情况
- 子节点处理错误:使用
extend而非直接替换children,且仅当孙节点符合条件时才保留当前节点,导致上层节点无法被正确纳入结果 - 未处理节点自身符合条件的场景:如果当前节点就是符合要求的shot节点,代码未直接保留它
修正后的代码
def filter_data(data): filtered_data = [] for item in data: # 递归处理子节点,得到过滤后的子树 filtered_children = filter_data(item.get('children', [])) # 判断当前节点是否需要保留:要么自身是符合条件的shot节点,要么子树中有符合条件的节点 should_keep = (item.get('shotType') == 'shot' and item.get('has_children') is True) or len(filtered_children) > 0 if should_keep: # 复制节点并更新children为过滤后的结果 filtered_item = item.copy() filtered_item['children'] = filtered_children filtered_data.append(filtered_item) return filtered_data # 测试验证 result = filter_data(data) import json print(json.dumps(result, indent=2))
说明
修正后的递归逻辑:
- 先递归处理所有子节点,得到过滤后的子树列表
- 对每个节点,判断是否需要保留:要么节点自身是
shotType='shot'且has_children=True,要么其过滤后的子树不为空(说明子树中存在符合条件的节点) - 保留的节点会更新
children为过滤后的子树,确保层级结构完整
内容的提问来源于stack exchange,提问作者mamtha p
相关产品推荐
相关产品推荐

