在python中按值删除字典项的最佳方法是啥? [复制]
Posted
技术标签:
【中文标题】在python中按值删除字典项的最佳方法是啥? [复制]【英文标题】:What is the best way to remove a dictionary item by value in python? [duplicate]在python中按值删除字典项的最佳方法是什么? [复制] 【发布时间】:2015-05-26 22:40:33 【问题描述】:我想知道是否有 simple 方法可以从 python 字典 按值删除 one 或 more 字典元素.
我们有一本名为myDict
的字典:
myDict = 1:"egg", "Answer":42, 8:14, "foo":42
想要移除所有值等于42
的项目。
实施建议:
获取myDict
中具有特定值的所有键的列表(例如参见get key by value in dictionary。)
从myDict
中删除这个或多个dict元素(基于找到的键)(有关详细信息,请参阅Delete an element from a dictionary。)
那么,你认为现在用 Python 实现这个问题的最优雅和最“pythonic”的方式是什么?
【问题讨论】:
“获取 first ... myDict 中值的键”的愿望有点可疑,@elegent,作为 first 的概念i> 并不真正适用于字典。 @user1656850:是的,你完全正确!非常感谢您指出这一点。我更新了问题:) 【参考方案1】:你可以使用简单的dict
理解:
myDict = key:val for key, val in myDict.items() if val != 42
这样:
>>> key:val for key, val in myDict.items() if val != 42
8: 14, 1: 'egg'
【讨论】:
我不会将其命名为item, key
,而是将其命名为key, val
,并使用val != 42
,因为它在语义上更正确。
感谢您的回答! dict
-comprehension 是个好主意,但在我看来,问题是关于如何从字典中删除项目。我知道我们只需要将推导的结果字典分配给myDict
:myDict = key:val for key, val in myDict.items() if val != 42
,所以如果您方便,请更改您的答案。【参考方案2】:
您必须创建一个副本以进行迭代,因为在循环内更改字典的大小会导致 RunTimeError。使用 items() 遍历字典副本中的键、值对,并将每个值与您要查找的值进行比较。如果匹配,则从字典中删除该键。
for key, value in dict(myDict).items():
if value == 42:
del mydict[key]
在下面的 cmets 中添加问题的答案,因为它太大而无法发表评论。这是一个快速控制台会话,显示 mydict.copy()
和 dict(myDict)
完成相同的事情。
>>>import copy
>>>dict1 = 1:"egg", "Answer":42, 8:14, "foo":42
>>>dict2 = dict(dict1)
>>>dict3 = dict1.copy()
>>>dict4 = dict1
>>>dict1[1] = "egg sandwich"
>>>dict1
'Answer': 42, 1: 'egg sandwich', 'foo': 42, 8: 14
>>>dict2
'Answer': 42, 1: 'egg', 'foo': 42, 8: 14
>>>dict3
'Answer': 42, 1: 'egg', 'foo': 42, 8: 14
>>>dict4
'Answer': 42, 1: 'egg sandwich', 'foo': 42, 8: 14
>>>dict2['foo'] = "I pity the"
dict1
>>>'Answer': 42, 1: 'egg sandwich', 'foo': 42, 8: 14
>>>dict2
'Answer': 42, 1: 'egg', 'foo': 'I pity the', 8: 14
>>>dict3
'Answer': 42, 1: 'egg', 'foo': 42, 8: 14
>>>dict4
'Answer': 42, 1: 'egg sandwich', 'foo': 42, 8: 14
>>>dict4[8] = "new"
>>>dict1
'Answer': 42, 1: 'egg sandwich', 'foo': 42, 8: 'new'
>>>dict2
'Answer': 42, 1: 'egg', 'foo': 'I pity the', 8: 14
>>>dict3
'Answer': 42, 1: 'egg', 'foo': 42, 8: 14
>>>dict4
'Answer': 42, 1: 'egg sandwich', 'foo': 42, 8: 'new'
`
【讨论】:
myDict.copy()
效率更高
我同意。感谢您指出了这一点。这也可以工作并消除在循环之前创建副本的额外行:for key, value in dict(myDict).items():
@cruane:非常感谢您的回答!也许你可以根据你的命令编辑你的答案。
很高兴我能帮上忙。我将编辑答案以反映更改。
@PadraicCunningham:myDict.copy()
和 dict(myDict)
有什么区别?【参考方案3】:
您可以遍历副本并进行查找:
for k in myDict.copy():
if myDict[k] == 42:
del myDict[k]
或者只复制密钥:
myDict = 1:"egg", "Answer":42, 8:14, "foo":42
for k in list(myDict):
if myDict[k] == 42:
del myDict[k]
print(myDict)
8: 14, 1: 'egg'
如果你想改变原始字典,那应该是最有效的。
【讨论】:
谢谢!为什么要使用reversed()
来反转键列表?元素(即键和值对)未在字典中排序,因此在我看来更改顺序是不必要的步骤。
@elegent,试试不倒车,你会看到
...它有效! :) 顺便说一句,你不需要 3 个右括号...
@elegent,是的,一个错字。是的,实际上 list(dict) 将适用于 python2 和 3
好的,没问题,谢谢您的回答。我只是有点困惑。 :)【参考方案4】:
我喜欢遵循“命中列表”方法,您可以遍历字典,然后将要删除的内容添加到列表中,然后在迭代后从该列表中删除条目,如下所示:
命中列表 =[] for dictEntry: if test condition, hitList.append
在 hitList 中的条目: 删除字典[条目]
这只是一些伪代码,但我过去已经成功了
【讨论】:
我也更喜欢这种方法,因为不需要复制。它也适用于列表,只需存储索引,然后删除相应的元素,但首先从最高索引开始。【参考方案5】:使用字典理解。
如果您需要副本,请使用iteritems()
>>> k:v for k, v in myDict.iteritems() if v!=42
8: 14, 1: 'egg'
如果您不需要字典副本,您可以使用viewitems()
>>> k:v for k, v in myDict.viewitems() if v!=42
8: 14, 1: 'egg'
【讨论】:
请对不赞成票发表评论,以便我改进答案。 谢谢!在 Python 3.x 中,我们只使用.items()
而不是 .iteritems()
和 viewitems()
?
是的,python 3.x 和 2.x 存在差异,但是您的问题没有标记为 python 版本,所以我假设您正在寻找 2.x 解决方案。
是的,对不起,你是对的。如果您方便,您可以将这些额外信息添加到您的答案中,这样我们就可以看到两个 Python 版本之间的区别。 :)以上是关于在python中按值删除字典项的最佳方法是啥? [复制]的主要内容,如果未能解决你的问题,请参考以下文章