16

I have these keys:

keep = ["a","c"]

My dict:

testdict = {'
'a':'vala',
'b':'valb',
'c':'valc',
'd':'vald'
}

Desired output:

testdict = {
'a':'vala',
'c':'valc'
}

I want to remove all keys that do not match the key in the list. What is the fastest way to do this?

I tried:

for key, value in testdict.iteritems():
      if key not in keep:
         del testdict[key]

But the above gives me errors since the size is changing.

Setsuna
  • 1,971
  • 7
  • 30
  • 49

3 Answers3

27

Instead of removing, simply construct a new dict:

newdict = {k: testdict[k] for k in keep}

If keep can contain keys that are not present in testdict, add the appropriate condition:

newdict = {k: testdict[k] for k in keep if k in testdict}

If you absolutely must modify the dict object, bear in mind that you can not modify a dictionary while you're traversing over it. So traverse first and delete afterwards:

to_delete = set(testdict.keys()).difference(keep)
for d in to_delete:
    del testdict[d]
phihag
  • 263,143
  • 67
  • 432
  • 458
  • You get a KeyError if k is not in testdict. Would `newdict = {k: testdict[k] for k in keep if k in testdict}` not be better? – msw Sep 22 '15 at 21:39
  • or possibly `{k: testdict.get(k, None) for k in keep}` – Adam Smith Sep 22 '15 at 21:40
  • @msw In general, I'd *want* an exception if keep is invalid, instead of later finding "invalid" dicts and guessing where they came from. But this depends on the specific use case. I've amended the answer. – phihag Sep 22 '15 at 21:42
  • @phihag I agree, there is not quite enough information in the OP to choose between the two. Elegant answer, regardless. – msw Sep 22 '15 at 21:44
  • no need to constuct a new dict: `testdict = {k: testdict[k] for k in keep if k in testdict}`, regardless a nice answer above! – Robert Nagtegaal Apr 30 '20 at 17:19
2

The problem is you're mutating the keys while using the iterator. If you had a proper list of the keys you could avoid the issue..

for key in list(testdict.keys()):
      if key not in keep:
         del testdict[key]
arco444
  • 20,737
  • 10
  • 61
  • 64
Chad S.
  • 5,446
  • 12
  • 25
1
print({k:testDict[k] for k in keep})

or in py<2.7

print dict((k,testDict[k]) for k in keep)

these assume every key in keep is guaranteed to exist in testDict

Joran Beasley
  • 103,130
  • 11
  • 146
  • 174
  • Dict comprehensions are available in Python 2.7! In any case, why are you constructing a list just to feed into dict instead of using a generator expression? – phihag Sep 22 '15 at 21:40