You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)

问题分析

当前代码存在三个核心问题:

  1. 筛选逻辑颠倒:只检查过滤后的子节点的孙节点是否符合条件,忽略了当前节点本身或直接子节点符合条件的情况
  2. 子节点处理错误:使用extend而非直接替换children,且仅当孙节点符合条件时才保留当前节点,导致上层节点无法被正确纳入结果
  3. 未处理节点自身符合条件的场景:如果当前节点就是符合要求的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 09:55:59