如何用一个字典过滤另一个字典?迭代时字典大小变更报错排查
解决字典迭代时修改导致的"迭代期间字典大小已更改"错误
我需要基于两个字典A和B创建第三个字典C,要求C包含A的全部键值对,但移除B中指定的键值对。我写了如下代码:
A = {"A": {"B": 6, "C": 5}, "B": {"A": 6, "D": 7, "E": 5}, "C": {"A": 5}, "D": {"B": 7, "E": 10, "H": 25}, "E": {"D": 10, "F": 14, "B": 5}, "F": {"E": 14}, "H": {"D": 25}} B = {"A": "C"} C = A for key, value in A.items(): C.update({key: value}) if key in B: for i in value: if i not in B.values(): C[key].pop(i) print(C)
预期输出是:
{"A": {"B": 6}, "B": {"A": 6, "D": 7, "E": 5}, "C": {"A": 5}, "D": {"B": 7, "E": 10, "H": 25}, "E": {"D": 10, "F": 14, "B": 5}, "F": {"E": 14}, "H": {"D": 25}}
但运行时终端报错:迭代期间字典大小已更改
错误原因
- 引用赋值导致原字典被修改:
C = A不是创建新字典,而是让C和A指向同一个字典对象。后续修改C的同时也会修改A,而你正在迭代A的键值对,这会干扰迭代过程。 - 迭代字典时修改其大小:内层循环
for i in value中,value是A[key](和C[key]是同一个子字典),执行pop(i)会直接修改这个子字典的大小,Python不允许在迭代字典的同时修改其大小,因此抛出错误。
修正方案
- 对A进行深拷贝得到C,确保修改C不会影响原字典A。
- 迭代子字典键的副本(比如转成列表),这样即使原字典大小改变,迭代的是固定的副本,不会触发错误。
修正后的代码:
import copy A = {"A": {"B": 6, "C": 5}, "B": {"A": 6, "D": 7, "E": 5}, "C": {"A": 5}, "D": {"B": 7, "E": 10, "H": 25}, "E": {"D": 10, "F": 14, "B": 5}, "F": {"E": 14}, "H": {"D": 25}} B = {"A": "C"} # 深拷贝A得到独立的C C = copy.deepcopy(A) for key, value in C.items(): if key in B: # 迭代子字典键的副本,避免迭代时修改字典大小 for i in list(value.keys()): if i != B[key]: C[key].pop(i) print(C)
代码说明
copy.deepcopy(A):完全复制A的所有层级结构,C成为独立的字典,修改C不会影响A。list(value.keys()):将子字典的键转换成列表,迭代这个固定的列表,即使后续pop修改子字典,也不会影响迭代过程。- 直接判断
i != B[key]比i not in B.values()更精准,因为B中每个key对应唯一要保留的子键。
内容的提问来源于stack exchange,提问作者Isabel
相关产品推荐
相关产品推荐

