在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 字典 按值删除 onemore 字典元素.

我们有一本名为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中按值删除字典项的最佳方法是啥? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

在Python中按值对嵌套字典进行排序,并按另一个值对余数进行排序

在c ++ 11中按值捕获成员变量的好方法是啥? [复制]

在 PHP 中删除数组项的最佳方法是啥?

在 JavaScript 中按值对字典进行排序

如何在 C# 字典中按值索引过滤项目?

在字典中按值获取键