21

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
  • 2,081
  • 7
  • 32
  • 50

3 Answers3

35

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
  • 278,196
  • 72
  • 453
  • 469
  • 1
    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
3
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
  • 110,522
  • 12
  • 160
  • 179
  • 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
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
  • 22,002
  • 12
  • 63
  • 67
Chad S.
  • 6,252
  • 15
  • 25