Python: Split list of dicts by key

Viewed 666

If I have a bunch of dicts in a list like:

people = [{"name": "Abe", "age": 40},
          {"name": "Bob", "age": 25},
          {"name": "Charles", "age": 32}]

I want to split it so it looks like

names = ["Abe", "Bob", "Charles"]
ages = [40, 25, 32]

I know I can do two separate list comprehensions (ex: names = [person["name"] for person in people] twice), but is there any trick to split this data in a one-liner?

4 Answers

You can use the zip trick:

>>> names, ages = zip(*(d.values() for d in people))
>>> names
('Abe', 'Bob', 'Charles')
>>> ages
(40, 25, 32)

Note that this will only work on Python 3.7 and later as dictionaries are insertion ordered in those versions.

You can use zip and map dict.values to the list:

names, ages = zip(*map(dict.values, people))

>>> names
('Abe', 'Bob', 'Charles')
>>> ages
(40, 25, 32)

Of course they are tuples but that's easy enough to resolve by mapping list to the unzipped result:

names, ages = map(list, zip(*map(dict.values, people)))

>>> names
['Abe', 'Bob', 'Charles']
>>> ages
[40, 25, 32]

Assuming your dicts share structure (same set of keys), you can aggregate values per key with:

>>> import operator
>>> keys = people[0].keys()
>>> getter = operator.itemgetter(*keys)
>>> dict(zip(keys, zip(*map(getter, people))))
{'name': ('Abe', 'Bob', 'Charles'), 'age': (40, 25, 32)}

Works in any Python (ordered dict not required), and it's handy for large number of keys/variables.

You can do it with list comprehension extracting the field names you want from the dictionaries:

people = [{"name": "Abe", "age": 40},
          {"name": "Bob", "age": 25},
          {"name": "Charles", "age": 32}]

names,ages = ([p[field] for p in people] for field in ("name","age"))

print(names)  # ['Abe', 'Bob', 'Charles']

print(ages)   # [40, 25, 32]
Related