Best way to pop many elements from a Python dict
Asked Answered
V

8

48

This is my code:

a = dict(aa='aaaa', bb='bbbbb', cc='ccccc', ...)
print(a.pop(['cc', ...]))

but this raises an error. What is the best simple way to pop many elements from a python dictionary?

Valero answered 17/3, 2011 at 1:36 Comment(0)
V
68

How about the simple:

for e in ['cc', 'dd',...]: 
  a.pop(e)
Venezuela answered 17/3, 2011 at 1:39 Comment(3)
That's a nice, simple and clean way to remove several elements. If you want to pop them, you'll probably find no simpler solution than to use pop in a list comprehension. While it's not exactly "hygienic", it is what he wanted ;)Backhander
If using a.keys() in the loop so as to not write out all the keys, make sure to use list(a.keys()) otherwise it will complain.Ytterbite
But this answer doesn't capture the popped values as the question implies.Martell
T
38

Using list comprehension:

a = {'key1':'value1','key2':'value2','key3':'value3'}
print [a.pop(key) for key in ['key1', 'key3']]
Tarra answered 17/3, 2011 at 1:43 Comment(2)
This works for me (thanks!) but I have a quick follow up question: isn't the result of a list comprehension a list? That would imply that your print statement would print a list containing a dict. But, this seems to deliver just the dict (i.e. the dict you started with minus the popped keys). Why? Thanks!Allonge
@Allonge If you just use the print statement (so not a = [a.pop(key) ...]), the executed statement won't save the result in any variable, but the a.pop is still carried out. So the elements are popped out of a, but the result of that popping is not stored anywhere.Stacistacia
B
6

If I understand correctly what you want, this should do the trick:

print [a.pop(k) for k in ['cc', ...]]

Be careful, though, because pop is destructive, i.e. it modifies your dictionary.

Backhander answered 17/3, 2011 at 1:43 Comment(0)
V
5

I've peformed a benchmark:

d = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6}
drop = ('a', 'b', 'x', 'y', 'z')

Test 1: d.pop(k, None). Note the second argument: it makes sure that missing keys don't fail

for key in drop:
    d.pop(key, None)

Test 2: if key in d: d.pop(). Will this extra condition slow things down or improve the performance of .pop()?

for key in drop:
    if key in d:
        d.pop(key)

Test 3: bad set

bad = set(d) & set(drop)  # find bad keys to drop

for key in bad:
    del d[key]

Test 4: create a new dict as comprehension

d = {k: v for k, v in d.items() if k not in drop}

Results:

  • .pop(key, None): 4.37s
  • if key in d: pop(): 3.75s
  • if key in set(bad): del d[key]: 5.27s
  • comprehension: 7.2s

Conclusions:

  • Dict comprehension has the worst performance
  • del is not too good
  • Both .pop() solutions are fine. Don't worry about an extra if: it actually improves things

Finally, Python is still able to 2 million times a second. Don't worry about it much :)

Varney answered 20/1, 2022 at 11:42 Comment(0)
P
3
a={'aa':'aaaa','bb':'bbbbb','cc':'ccccc'}
remove = ['aa', 'cc']
newA = dict([(k, v) for k,v in a.items() if k not in remove])
Prasad answered 17/3, 2011 at 1:44 Comment(2)
make remove a set, it will be quickerWatercool
You don't need the square brackets in the last line, @MikeLewis. You're just creating a superfluous list and throwing it away again.Martell
A
2

Here is a one-liner, that will work on arbitrary long dictionary, for this exact case:

print([a.pop(key) for key in list(a.keys()) if key >= 'cc'])

To illustrate:

a = dict(aa='aaaa', bb='bbbbb', cc='ccccc', dd='ddddd', ee='eeeee')
print([a.pop(key) for key in list(a.keys()) if key >= 'cc']) # => ['ccccc', 'ddddd', 'eeeee']
print(a) # => {'aa': 'aaaa', 'bb': 'bbbbb'}

Note: it'll work as long as dictionary keys are "incremented" as follows: aa, bb, cc, dd, ee, ff, ...

Amphiarthrosis answered 18/7, 2018 at 6:1 Comment(0)
M
0

Nobody has shown how to subtract the popped pairs as a separate dict. Not explicitly in the question, but still answers the question (as shown below) and has the added value of the popped keys and values captured in a separate dict:

>>> a = dict(aa='aaaa', bb='bbbbb', cc='ccccc', dd='ddddd', ee='eeeee')
>>> subtracted = dict((key, a.pop(key)) for key in ['cc', 'dd'])

>>> a
{'aa': 'aaaa', 'bb': 'bbbbb', 'ee': 'eeeee'}

>>> print(subtracted)
{'cc': 'ccccc', 'dd': 'ddddd'}

>>> print(list(subtracted.values()))
['ccccc', 'ddddd']
Martell answered 24/4 at 13:3 Comment(0)
L
-2

your_dict.clear() might also be an option

Lashanda answered 10/3, 2023 at 10:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.