
本文详解如何正确过滤“字典套列表套字典”三层嵌套结构中满足 end_date == 99999999 的内层字典,指出原始写法误用 positions.values() 导致逻辑错位,并提供可复用的字典推导式解决方案。
本文详解如何正确过滤“字典套列表套字典”三层嵌套结构中满足 end_date == 99999999 的内层字典,指出原始写法误用 positions.values() 导致逻辑错位,并提供可复用的字典推导式解决方案。
你遇到的问题本质是混淆了过滤层级:原始代码 for position in positions.values() 遍历的是每个股票对应的整个列表(如 IBM 对应的 3 个字典组成的列表),而条件 position[0].get('end_date') == 99999999 只检查该列表首个元素的 end_date,一旦满足,就将整个列表无差别保留——这正是你得到全部三条记录的原因。
要真正实现“只保留每个列表中 end_date 等于 99999999 的字典”,必须在最内层列表上执行过滤,而非对列表整体做判断。推荐使用字典推导式 + 列表推导式嵌套,既保持结构清晰,又精准定位目标数据:
positions = {
'IBM': [
{'ticker': 'IBM', 'start_date': '20240415', 'end_date': 99999999},
{'ticker': 'IBM', 'start_date': '20240416', 'end_date': 0},
{'ticker': 'IBM', 'start_date': '20240417', 'end_date': 99999999}],
'MRK': [
{'ticker': 'mmm', 'start_date': '20240415', 'end_date': 99999999},
{'ticker': 'mmm', 'start_date': '20240416', 'end_date': 0},
{'ticker': 'mmm', 'start_date': '20240417', 'end_date': 99999999}]
}
# ✅ 正确做法:逐 key 遍历,对每个 value(即列表)内部逐字典过滤
new_pos = {
key: [pos for pos in value if pos.get('end_date') == 99999999]
for key, value in positions.items()
}
print(new_pos)
# 输出:
# {
# 'IBM': [
# {'ticker': 'IBM', 'start_date': '20240415', 'end_date': 99999999},
# {'ticker': 'IBM', 'start_date': '20240417', 'end_date': 99999999}
# ],
# 'MRK': [
# {'ticker': 'mmm', 'start_date': '20240415', 'end_date': 99999999},
# {'ticker': 'mmm', 'start_date': '20240417', 'end_date': 99999999}
# ]
# }
关键要点说明:
- positions.items() 同时获取键(如 'IBM')和值(对应字典列表),确保新字典保留原始键名;
- 内层 [pos for pos in value if ...] 在每个列表内部独立过滤,pos 是单个字典,pos.get('end_date') 安全访问字段(避免 KeyError);
- 若需进一步处理(如按 start_date 排序或去重),可在列表推导式后链式调用,例如:
[pos for pos in value if pos.get('end_date') == 99999999].sort(key=lambda x: x['start_date'])
注意事项:
⚠️ 避免使用 position[0] 这类硬编码索引——若某列表为空会引发 IndexError;优先用 .get() 并结合明确条件;
⚠️ 00000000 在 Python 中会被解释为整数 0(八进制前缀 0o 才表示八进制),确保日期数值类型一致;
✅ 此方案时间复杂度为 O(N),N 为所有内层字典总数,是处理此类嵌套结构的最优实践。











