What is the best way to remove a dictionary item by value in python?

Question:

I wonder if there is simple way to remove one or more dictionary element(s) from a python dictionary by value.

We have a dictionary called myDict:

myDict = {1:"egg", "Answer":42, 8:14, "foo":42}

and want to remove all items which values are equal to 42.

Implementation suggestion:

  1. Get a list of all keys of a certain value in myDict
    (See for instance get key by value in dictionary.)

  2. Delete this dict element or elements (based on the found keys) from myDict
    (For more information, see Delete an element from a dictionary.)

So, what do you think now is the most elegant and most “pythonic” way to implement this problem in Python?

Asked By: elegent

||

Answers:

You can use a simple dict comprehension:

myDict = {key:val for key, val in myDict.items() if val != 42}

As such:

>>> {key:val for key, val in myDict.items() if val != 42}
{8: 14, 1: 'egg'}
Answered By: A.J. Uppal

You must create a copy to iterate over as changing the size of the dictionary inside of a loop causes a RunTimeError. Iterate over key, value pairs in your dictionary copy using items() and compare each value to the value you are looking for. If they match, delete the key from the dictionary.

    for key, value in dict(myDict).items():
        if value == 42:
            del mydict[key]

Adding answer for question in the comments below as it was too big for a comment. Here is a quick console session showing that mydict.copy() and dict(myDict) accomplish the same thing.

>>>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'}
`
Answered By: cruane

Use a dictionary comprehension.

if you need a copy use iteritems()

>>> {k:v for k, v in myDict.iteritems() if v!=42}
{8: 14, 1: 'egg'}

if you don’t need a copy of your dictionary you can use viewitems()

>>> {k:v for k, v in myDict.viewitems() if v!=42}
{8: 14, 1: 'egg'}
Answered By: kasper Taeymans

You can iterate over a copy and do a lookup:

for k in myDict.copy():
    if myDict[k] == 42:
        del myDict[k]

Or only copy the keys:

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'}

Which if you want to mutate the original dict should be the most efficient.

Answered By: Padraic Cunningham

I like following a “hit list” approach where you iterate through the dictionary, then add the ones you want to delete to a list, then after iterating, delete the entries from that list like so:

hitList =[]
for dictEntry: if test condition, hitList.append

for entry in hitList:
delete dict[entry]

this is just some pseudocode but i’ve been successful with this in the past

Answered By: NevDev