Laurie
Laurie

Reputation: 1229

Specifying nested dictionary key in list of arguments

I have a function which iterates over a list of dicts, returning specified key-value pairs into a new list of dicts:

data = [
    {'user': {'login': 'foo1', 'id': 'bar2'}, 'body': 'Im not sure', 'other_field': 'value'},
    {'user': {'login': 'foo2', 'id': 'bar3'}, 'body': 'Im still not sure', 'other_field': 'value'},
]

filtered_list = []
keys = ['user','body']

for i in data:
    filt_dict = dict((k, i[k]) for k in keys if k in i)
    filtered_list.append(filt_dict)

The user key contains a sub-key called login; how can this be added to the keys argument list, instead of the key user?

Sample output:

filtered_list = [
    {'login': 'foo1', 'body': 'Im not sure'},
    {'login': 'foo2', 'body': 'Im still not sure'},
]

Upvotes: 3

Views: 323

Answers (2)

Ralf
Ralf

Reputation: 16505

If you are certain, that all elements (dicts) in the list will have the keys you specified, then a quick solution could be this:

filtered_list = [
    {
        'login': elem['user']['login'],
        'body': elem['body'],
    }
    for elem in data]

This has no error handling for missing keys.

Upvotes: 1

timgeb
timgeb

Reputation: 78700

How about this? Assumes your chain of keys actually exists in the dicts you are iterating.

Setup

>>> from functools import reduce
>>> data = [{'user': {'login': 'foo1', 'id': 'bar2'}, 'body': 'Im not sure', 'other_field': 'value'},
...         {'user': {'login': 'foo2', 'id': 'bar3'}, 'body': 'Im still not sure', 'other_field': 'value'}]
>>> keys = [('user', 'login'), ('body',)]

Solution

>>> [{ks[-1]: reduce(dict.get, ks, d) for ks in keys} for d in data]
[{'body': 'Im not sure', 'login': 'foo1'}, {'body': 'Im still not sure', 'login': 'foo2'}]

Upvotes: 5

Related Questions