在Python中,我可以在遍历字典时删除字典中的项吗?
我想从字典中删除不符合特定条件的元素,而不是创建一个全新的字典。以下是一个好的解决方案,还是有更好的方法?
for k, v in mydict.items():
if k == val:
del mydict[k]
在Python中,我可以在遍历字典时删除字典中的项吗?
我想从字典中删除不符合特定条件的元素,而不是创建一个全新的字典。以下是一个好的解决方案,还是有更好的方法?
for k, v in mydict.items():
if k == val:
del mydict[k]
当前回答
如果想要删除的项总是在dict迭代的“开始”,有一种方法可能是合适的
while mydict:
key, value = next(iter(mydict.items()))
if should_delete(key, value):
del mydict[key]
else:
break
“开头”只保证在某些Python版本/实现中是一致的。例如,来自Python 3.7新提示
dict对象的插入顺序保存特性已被声明为Python语言规范的正式组成部分。
这种方法避免了许多其他答案所建议的字典副本,至少在Python 3中是这样。
其他回答
你可以使用字典理解法。
D = {k: D [k] for k in D if D [k] != val}
如果想要删除的项总是在dict迭代的“开始”,有一种方法可能是合适的
while mydict:
key, value = next(iter(mydict.items()))
if should_delete(key, value):
del mydict[key]
else:
break
“开头”只保证在某些Python版本/实现中是一致的。例如,来自Python 3.7新提示
dict对象的插入顺序保存特性已被声明为Python语言规范的正式组成部分。
这种方法避免了许多其他答案所建议的字典副本,至少在Python 3中是这样。
对于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()返回的是一个迭代器而不是一个列表。 正如在评论中指出的那样,只需将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的值进行删除,请使用items()方法:
>>> for k, v in mydict.items():
... if v == 3:
... del mydict[k]
>>> mydict
{'four': 4, 'one': 1}
一行程序:
my_dict = {k: v for k, v in my_dict.copy().items() if not k == value}
my_dict.copy()对象仅用于迭代,在字典理解范围之外不可用。这避免了编辑当前迭代的对象,正如@user395760在回答中所建议的那样。
为了清晰起见,你可以把它分割成多行:
my_dict = {
k: v
for k, v in my_dict.copy().items()
if not k == value
}
在迭代集合时不能修改集合。这种方式是疯狂的——最明显的是,如果你被允许删除和删除当前项,迭代器将不得不移动(+1),而下一次调用next将超出(+2),所以你最终会跳过一个元素(在你删除的元素后面的那个元素)。你有两个选择:
Copy all keys (or values, or both, depending on what you need), then iterate over those. You can use .keys() et al for this (in Python 3, pass the resulting iterator to list). Could be highly wasteful space-wise though. Iterate over mydict as usual, saving the keys to delete in a seperate collection to_delete. When you're done iterating mydict, delete all items in to_delete from mydict. Saves some (depending on how many keys are deleted and how many stay) space over the first approach, but also requires a few more lines.