48

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?

2
  • The desire to "Get the first ... key of a value in myDict" is a bit dubious, @elegent, as the notion of first doesn't really apply to dictionaries. Commented Mar 24, 2015 at 18:27
  • @user1656850: Yes, you are absolutely right! Thank you very much for pointing that out. I updated the question :) Commented Mar 24, 2015 at 18:48

5 Answers 5

78

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'}
Sign up to request clarification or add additional context in comments.

2 Comments

I would not name it item, key and would name it key, val instead and use val != 42 because it's more semantically correct.
Thanks for your answer! A dict-comprehension is a nice idea, but in my opinion the question was about how to remove items form a dict. I know that we only need to assign the resulting dict of the comprehension to myDict: myDict = {key:val for key, val in myDict.items() if val != 42}, so if it is convenient to you please change your answer.
11

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

7 Comments

myDict.copy() is more efficient
I agree. Thanks for pointing that out. This would also work and eliminate the extra line of creating a copy before the loop: for key, value in dict(myDict).items():
@cruane: Thank you very much for your answer! Maybe you can edit your answer according to your command.
Glad I could help. I will edit the answer to reflect the changes.
@PadraicCunningham: What is the differnce between myDict.copy() and dict(myDict)?
|
2

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

1 Comment

I prefer this approach too, beacuse no copy has to be made. It is applicable to a list too, just store the indices and then delete the corresponding elements, but starting with the highest index first.
2

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.

5 Comments

Thanks! Why should we use reversed() to reverse the list of keys? The elements (i.e. the key and value pairs) are not sorted in a dict, therefore changing the order is a unnecessary step in my opinion.
@elegent, try doing it without reversing and you will see
... that it works! :) BTW, you don’t need 3 closing parenthesis...
@elegent, yep a typo. Yes actually list(dict) will work for python2 and 3
Ok no problem, thank you for your answer. I was just a little bit confused. :)
0

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

4 Comments

please leave a comment for the downvote so I can improve my answer.
Thanks! In Python 3.x we only use .items() instead of .iteritems() and viewitems()?
yes there are differences in python 3.x and 2.x however your question is not tagged with a python version so I assumed you were looking for a 2.x solution.
Yes, sorry you are right. If it is convenient to you, you could add this extra information to your answer, so we can see the difference between the two Python versions. :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.