igorgue
igorgue

Reputation: 18252

How to delete all the items of a specific key in a list of dicts?

I'm trying to remove some items of a dict based on their key, here is my code:

d1 = {'a': 1, 'b': 2}
d2 = {'a': 1}

l = [d1, d2, d1, d2, d1, d2]

for i in range(len(l)):
    if l[i].has_key('b'):
        del l[i]['b']

print l

The output will be:

[{'a': 1}, {'a': 1}, {'a': 1}, {'a': 1}, {'a': 1}, {'a': 1}]

Is there a better way to do it?

Upvotes: 0

Views: 309

Answers (4)

Lennart Regebro
Lennart Regebro

Reputation: 172377

I like your way of doing it (except that you use a loop variable, but others pointed that out already), it's excplicit and easy to understand. If you want something that minimizes typing then this works:

[x.pop('b', None) for x in l]

Note though that only one 'b' will be deleted, because your list l references the dictionaries. So run your code above, and then print out d1, and you'll notice that in fact you deleted the b-key from d1 as well.

To avoid this you need to copy the dictionaries:

d1 = {'a': 1, 'b': 2}
d2 = {'a': 1}

l = [d1.copy(), d2.copy(), d1.copy(), d2.copy(), d1.copy(), d2.copy()]
[b.pop('b', None) for b in l]

d1 will now retain the b key.

Upvotes: 2

Nikokrock
Nikokrock

Reputation: 82

d1 = {'a': 1, 'b': 2} d2 = {'a': 1}

l = [d1, d2, d1, d2, d1, d2]

for i in range(len(l)): if l[i].has_key('b'): del l[i]['b']

print l

Here is little review of your code:

  1. iterating on list is not done like in C. If you don't need reference the list index it's better to use for item in l and then replace l[i] by item.
  2. for key existence test you can just write if 'b' in l[i]

So your code becomes:

for item in l:
    if 'b' in item:
        del item['b']

One more thing you need to be careful is that on the first iteration that calls del, you will in fact delete all you need as d1 is mutable. You need to think that d1 is a reference and not the value (a bit like a pointer in C).

As Lennart Regebro mentioned to optimize your code you can also use list comprehension.

Upvotes: 0

Kathy Van Stone
Kathy Van Stone

Reputation: 26281

A slight simplification:

   for d in l:
      if d.has_key('b'):
         del d['b']

Some people might also do

   for d in l:
      try:
         del d['b']
      except KeyError:
         pass

Catching exceptions like this is not considered as expensive in Python as in other languages.

Upvotes: 3

Danra
Danra

Reputation: 9936

d1 = {'a': 1, 'b': 2}
d2 = {'a': 1}
l = [d1, d2, d1, d2, d1, d2]
for d in l:
    d.pop('b',None)
print l

Upvotes: 16

Related Questions