jamiet
jamiet

Reputation: 12264

Operate on dicts nested inside a list using a list comprehension

I have a list of dicts, each dict has a data key. Each data key contains a bunch of attributes about a person, none of those attributes are mandatory:

persons = [
    {"Name": "John", "data": {"Age": 23, "Gender": "Male"}},
    {"Name": "Jane", "data": {"Age": 22, "Gender": "Female"}},
    {"Name": "Harry", "data": {"Age": 22}},
    {"Name": "Hermione", "data": {"Gender": "Female"}},
]

What I'd like to do is extract a distinct list of the Age values. I've done it like this:

ages = set()
persondatas = [person['data'] for person in persons]
for persondata in persondatas:
    if 'Age' in persondata:
        ages.add(persondata['Age'])
ages

which returns:

{22, 23}

which is exactly what I want but I'm thinking there must be a better, neater, way than looping over a list that I obtained using a list comprehension. Can I do the required work inside a list comprehension perhaps? My first aborted attempt went like this: [person['data']['Age'] for person in l] which failed:

KeyError: 'Age'

There must be a better way but I've fiddled around and can't work it out. Can anyone help?

Upvotes: 2

Views: 58

Answers (3)

jpp
jpp

Reputation: 164673

One solution is a list comprehension combined with filter.

set(filter(None, [p['data'].get('Age') for p in persons]))

Upvotes: 0

goodvibration
goodvibration

Reputation: 6206

Try this:

ages = set([person["data"]["Age"] for person in persons if "Age" in person["data"]])

Upvotes: 1

TerryA
TerryA

Reputation: 59974

You could add a conditional into your list comprehension - knock out both operations with one loop.

>>> {person['data']['Age'] for person in persons if 'Age' in person['data']}
set([22, 23])

Notice how I use curly braces ({}), instead of square brackets ([]), to denote a set comprehension.

Upvotes: 4

Related Questions