在遍历字典时如何删除其中的项?
我可以在遍历Python字典的时候删除里面的项目吗?
我想把那些不符合某个条件的元素从字典里去掉,而不是重新创建一个新的字典。下面这个方法好不好,还是有没有更好的办法呢?
for k, v in mydict.items():
if k == val:
del mydict[k]
12 个回答
35
可以遍历一个副本,比如用 items()
返回的那个副本:
for k, v in list(mydict.items()):
118
你也可以分两步来做:
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)
440
对于Python 3+:
>>> mydict
{'four': 4, 'three': 3, 'one': 1}
>>> for k in list(mydict.keys()):
... if mydict[k] == 3:
... del mydict[k]
>>> mydict
{'four': 4, 'one': 1}
其他的答案在Python 2中运行得很好,但在Python 3中会出现一个RuntimeError
错误:
RuntimeError: 在迭代过程中字典的大小发生了变化。
这个错误发生是因为mydict.keys()
返回的是一个迭代器,而不是一个列表。正如评论中提到的,只需通过list(mydict.keys())
将mydict.keys()
转换为列表,这样就可以正常工作了。
对于Python 2:
在控制台做个简单测试,你会发现不能在遍历字典的时候修改它:
>>> 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}