
本文介绍如何在 python 中筛选嵌套字典(如按值长度过滤),并重新连续编号键(从 0 开始递增),解决因原键不连续导致的索引错位问题。
在处理以整数为键、列表为值的嵌套字典时,常需按值的特征(如长度)进行过滤。但直接使用 del 删除元素会导致键不再连续,影响后续按序访问或序列化需求。例如:
a = {0: [1, 2], 1: [3, 4, 5], 2: [6, 7, 8]}
for i in range(len(a)):
if len(a[i]) != 3:
del a[i]
# 此时 a 变为 {1: [3, 4, 5], 2: [6, 7, 8]} —— 键未重排,仍保留原始编号⚠️ 注意:上述循环存在运行时错误风险——在遍历字典的同时修改其长度(del)可能导致 KeyError 或跳过元素(因 range(len(a)) 在循环开始时已固定,而字典实际大小动态变化)。更安全的做法是先收集待删键,再统一删除;或直接构建新字典。
推荐采用函数式、一次性重构方式,兼顾安全性与可读性:
a = {0: [1, 2], 1: [3, 4, 5], 2: [6, 7, 8]}
# 步骤1:筛选出值长度为3的项,并按原键排序(确保顺序稳定)
filtered_items = [(k, v) for k, v in a.items() if len(v) == 3]
filtered_items.sort(key=lambda x: x[0]) # 按原键升序排列
# 步骤2:用 enumerate 生成新键(0, 1, 2...),重建字典
reordered = {i: v for i, (k, v) in enumerate(filtered_items)}
print(reordered) # 输出:{0: [3, 4, 5], 1: [6, 7, 8]}也可进一步简化为单行表达式(适合逻辑清晰、数据量不大的场景):
reordered = {i: v for i, (_, v) in enumerate(
sorted((k, v) for k, v in a.items() if len(v) == 3)
)}✅ 关键要点总结:
- 避免在 for 循环中直接修改正在遍历的字典;
- 使用 items() + 列表推导式实现安全过滤;
- sorted(...) 确保重编号前的顺序可控(尤其当原始键无序时);
- enumerate() 是重编号最直观、高效的工具;
- 若需保持插入顺序(Python 3.7+ 字典有序),且原始键本就有序,sorted() 可省略,但显式排序更健壮。
该方法通用性强,适用于任何需“过滤 + 连续重索引”的字典场景,如数据预处理、批量任务编号、JSON 序列化准备等。










