如何在迭代时从字典中删除项目?
在迭代Python时从Python字典中删除项目是否合法?
例如:
for k, v in mydict.iteritems():
if k == val:
del mydict[k]
这个想法是从字典中移除不符合特定条件的元素,而不是创建一个新的字典,它是被迭代的字典的子集。
这是一个好的解决方案吗? 有更多优雅/有效的方法吗?
在控制台中进行的简单测试表明,在迭代它时不能修改字典:
>>> mydict = {'one': 1, 'two': 2, 'three': 3, 'four': 4}
>>> for k, v in mydict.iteritems():
... if k == 'two':
... del mydict[k]
...
------------------------------------------------------------
Traceback (most recent call last):
File "<ipython console>", line 1, in <module>
RuntimeError: dictionary changed size during iteration
正如delnan的回答所述,当迭代器试图移动到下一个条目时,删除条目会导致问题。 相反,使用keys()
方法获取密钥列表并使用它:
>>> for k in mydict.keys():
... if k == 'two':
... del mydict[k]
...
>>> mydict
{'four': 4, 'three': 3, 'one': 1}
如果需要根据项目值删除,请改用items()
方法:
>>> for k, v in mydict.items():
... if v == 3:
... del mydict[k]
...
>>> mydict
{'four': 4, 'one': 1}
编辑:
以上不适用于Python3,并会产生RuntimeError
。
RuntimeError:迭代期间字典更改大小。
发生这种情况是因为mydict.keys()
返回一个迭代器而不是一个列表。 正如在注释中指出的,只需将mydict.keys()
转换为list(mydict.keys())
,它就可以工作。
您也可以分两步进行:
remove = [k for k in mydict if k == val]
for k in remove: del mydict[k]
我最喜欢的方法通常是制作一个新的字典:
# Python 2.7 and 3.x
mydict = { k:v for k,v in mydict.items() if k!=val }
# before Python 2.7
mydict = dict((k,v) for k,v in mydict.iteritems() if k!=val)
迭代它时不能修改集合。 这会带来疯狂-最明显的是,如果你被允许删除,并删除了当前项目,迭代器将不得不继续前进(+1),并在下次调用next
将带您超出(+2),所以你” d最终跳过一个元素(在删除的元素后面)。 你有两个选择:
.keys()
等等(在Python 3中,将生成的迭代器传递给list
)。 虽然可能会非常浪费空间。 mydict
,将密钥保存在一个单独的集合to_delete
。 当您完成迭代mydict
,删除所有项目to_delete
从mydict
。 在第一种方法中保存一些(取决于删除多少个键以及保留多少键),但还需要更多的线。 上一篇: How to delete items from a dictionary while iterating over it?