如何在迭代时从字典中删除项目?

在迭代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_deletemydict 。 在第一种方法中保存一些(取决于删除多少个键以及保留多少键),但还需要更多的线。
  • 链接地址: http://www.djcxy.com/p/18021.html

    上一篇: How to delete items from a dictionary while iterating over it?

    下一篇: What are "named tuples" in Python?