Python按name键值过滤任意深度嵌套字典的实现方案
嵌套字典按name字段过滤实现方案
原有dpath方案失效原因
dpath.util.search的核心逻辑是仅保留过滤函数返回True的节点,直接使用会出现两个不符合预期的问题:
- 没有
name字段的父级结构节点(比如顶层的type键、中间存储struct类型定义的无name字典)会因为不匹配过滤规则被直接丢弃 - 列表中不符合规则的元素不会被真正移除,只会被置为
null占位
纯Python递归实现
不需要依赖第三方库,可适配任意嵌套深度的字典/列表结构,过滤时自动保留所有父级层级,仅移除name不在允许列表的字典项,不会残留null占位:
def filter_dict_by_name(node, allowed_names): # 处理字典节点 if isinstance(node, dict): # 带name字段的节点,不在允许列表直接返回None标记为待丢弃 if "name" in node and node["name"] not in allowed_names: return None # 递归处理所有子键值 filtered_node = {} for key, value in node.items(): child_res = filter_dict_by_name(value, allowed_names) if child_res is not None: filtered_node[key] = child_res return filtered_node # 处理列表节点 elif isinstance(node, list): filtered_list = [] for item in node: child_res = filter_dict_by_name(item, allowed_names) # 仅保留未被标记丢弃的子项,不保留null占位 if child_res is not None: filtered_list.append(child_res) return filtered_list # 基础类型(数字、字符串、空值等)直接返回 else: return node # 调用示例 if __name__ == "__main__": # 替换为你的原始字典 origin_dict = { "name":"a_struct", "type":"int", "data":{ "type":"struct", "elements":[ { "data":[ {"name":"test1","data_id":0,"type":"uint8","wire_type":0,"data":0}, {"name":"test2","data_id":2,"type":"uint32","wire_type":2,"data":0}, {"name":"test3","data_id":3,"type":"int","wire_type":4,"data":{"type":"uint32","elements":[]}}, {"name":"test4","data_id":4,"type":"uint32","wire_type":2,"data":0}, {"name":"test5","data_id":5,"type":"int","wire_type":4,"data":{"type":"uint32","elements":[]}} ] } ] } } allowed_name_list = ["test1", "test3", "test5"] result = filter_dict_by_name(origin_dict, allowed_name_list)
实现逻辑说明
- 所有不带
name字段的字典都属于结构父级节点,默认全部保留,仅递归处理内部嵌套值 - 带
name字段的字典会先做白名单校验,不在允许列表的直接标记丢弃 - 处理列表时会遍历所有子项递归过滤,直接剔除被标记丢弃的项,不会留下空占位
- 基础类型值(整数、字符串、空列表等)不做额外处理直接保留
- 运行上述代码得到的输出和预期过滤结果完全一致
内容的提问来源于stack exchange,提问作者Mav17
相关产品推荐
相关产品推荐

