Question or problem about Python programming:
I have a dictionary:
{'key1':1, 'key2':2, 'key3':3}
I need to pass a sub-set of that dictionary to third-party code. It only wants a dictionary containing keys [‘key1’, ‘key2’, ‘key99’] and if it gets another key (eg ‘key3’), it explodes in a nasty mess. The code in question is out of my control so I’m left in a position where I have to clean my dictionary.
What’s the best, way to limit a dictionary to a set of keys?
Given the example dictionary and allowed keys above, I want:
{'key1':1, 'key2':2}
How to solve the problem:
Solution 1:
In [38]: adict={'key1':1, 'key2':2, 'key3':3} In [41]: dict((k,adict[k]) for k in ('key1','key2','key99') if k in adict) Out[41]: {'key1': 1, 'key2': 2}
In Python3 (or Python2.7 or later) you can do it with a dict-comprehension too:
>>> {k:adict[k] for k in ('key1','key2','key99') if k in adict} {'key2': 2, 'key1': 1}
Solution 2:
dict(filter(lambda i:i[0] in validkeys, d.iteritems()))
Solution 3:
In modern Python (2.7+,3.0+), use a dictionary comprehension:
d = {'key1':1, 'key2':2, 'key3':3} included_keys = ['key1', 'key2', 'key99'] {k:v for k,v in d.items() if k in included_keys}
Solution 4:
An other solution without if in dict comprehension.
>>> a = {'key1':1, 'key2':2, 'key3':3} >>> b = {'key1':1, 'key2':2} >>> { k:a[k] for k in b.keys()} {'key2': 2, 'key1': 1}
Solution 5:
My way to do this is.
from operator import itemgetter def subdict(d, ks): return dict(zip(ks, itemgetter(*ks)(d))) my_dict = {'key1':1, 'key2':2, 'key3':3} subdict(my_dict, ['key1', 'key3'])
Update
I have to admit though, the above implementation doesn’t handle the case when the length of ks
is 0 or 1. The following code handles the situation and it is no longer an one-liner.
def subdict(d, ks): vals = [] if len(ks) >= 1: vals = itemgetter(*ks)(d) if len(ks) == 1: vals = [vals] return dict(zip(ks, vals))
Solution 6:
With a complex class Myclass
being a subclass of collections.UserDict
. To select a subset of it, i.e keeping all its container properties, it’s convenient to define a method, e.g. named sub
like so:
def sub(self, keys): subset = Myclass() # no arguments; works if defined with only keyword arguments for key in keys: subset[key] = self[key] return subset
It is then used as Myclass.sub([key1, key2 ...]
)