Rusty Lemur Rusty Lemur - 1 year ago 111
Python Question

Python create list from list of dictionaries for each dictionary that has a specific key

I have a list of dictionaries that do not necessarily have the same keys. I am trying to make a new list of the values contained in each dictionary that has a specific key.


dict1 = {'key1': 1, 'key2': 2, 'key4': 4}
dict2 = {'key2': 2, 'key3': 3}
dict3 = {'key1': 1, 'key2': 2, 'key3': 3}

dict_list = [dict1, dict2, dict3]

Now I'm trying to create a list from dict_list as follows:

key2vals = [dict['key2'] for dict in dict_list]
[2, 2, 2]

That works well, since 'key2' is contained in every dictionary in the list. However, when I try a key that does not appear in every dictionary, I get a fault. E.g. 'key1':

>>> key1vals = [dict['key1'] for dict in dict_list]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <listcomp>
KeyError: 'key1'

Is there a short and straightforward way that I can do something like the following, which does not work?

# This does not work
key1vals = [dict['key1'] if 'key1' in dict for dict in dict_list]

What is the most Pythonic way to accomplish this?

The order of the for and if statements should have been reversed:

key1vals = [dict['key1'] for dict in dict_list if 'key1' in dict ]

Also, with AbrahamB and DJV's suggestions, I was able to add a default value to those dictionaries without the search key:

[dict.get('key1', 0) for dict in dict_list]

Answer Source
dict1 = {'key1': 1, 'key2': 2, 'key4': 4}
dict2 = {'key2': 2, 'key3': 3}
dict3 = {'key1': 1, 'key2': 2, 'key3': 3}

dict_list = [dict1, dict2, dict3]

keys = ['key1', 'key2', 'key3', 'key4', 'key5']
for key in keys:
    values = [d[key] for d in dict_list if key in d]
[1, 1]
[2, 2, 2]
[3, 3]

The only issue with it is that item lookup is done twice for each element: key in d and d[key]. If that is important, then you can avoid this:

values = list(filter(None, (d.get(key) for d in dict_list)))

Edited: You mentiond in comments that you actually need 0 if key is not in dict.

values = [d.get('key1', 0) for d in dict_list]
[1, 0, 1]
[2, 2, 2]
[0, 3, 3]
[4, 0, 0]
[0, 0, 0]
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download