1

I have data in the form of a list of dicts, with some keys and values (the example below is for two keys/values, there could be more):

I would like to pythonically answer the question: what is john's age?

The simple solution I am using now is to iterate though the list and check for a matching value of name. Is there a more pythonic way to achieve the same?

data = [
    {
        'name': 'john',
        'age': 10
    },
    {
        'name': 'paul',
        'age': 20
    }
]

age = -1    # in case the name is not found
for d in data:
    if d['name'] == 'john':
        age = d['age']

print(age)
scytale
  • 12,346
  • 3
  • 32
  • 46
WoJ
  • 27,165
  • 48
  • 180
  • 345
  • 1
    No; unless you can rearrange to have a dictionary `{'john': 10, ...}` (then it's just `age = d.get('john', -1)`) that's as simple as you can get it. A `break` would improve the runtime, though. – jonrsharpe Aug 28 '15 at 10:18
  • Possible duplicate of http://stackoverflow.com/questions/8534256/find-first-element-in-a-sequence-that-matches-a-predicate – Tamas Hegedus Aug 28 '15 at 11:04

4 Answers4

1

I would use next() and a generator expression.

The generator expression would be a one line equivalent to your for loop , and next() would get the next value from it (which when called first time is the first value).

Example -

next((d['age'] for d in data if d['name'].lower() == 'john'), -1)

The second argument to -1 is like the default value to return in case the generator expression does not have anymore values (in this case - it means if the name - john does not exist in the list) .


Demo -

>>> data = [
...     {
...         'name': 'john',
...         'age': 10
...     },
...     {
...         'name': 'paul',
...         'age': 20
...     }
... ]
>>>
>>> next((d['age'] for d in data if d['name'].lower() == 'john'), None)
10
Anand S Kumar
  • 88,551
  • 18
  • 188
  • 176
0

You could create a dictionary with the name as key and age as value, then lookup the name:

age = {person['name']: person['age']
       for person in data}['john']
Peter Wood
  • 23,859
  • 5
  • 60
  • 99
0

Maybe what you want is a list of comprehension

age = [d['age'] for d in data if d['name'] == 'john'][0]

Also, you can use filter on the list this way :

age = filter(lambda u : u['name'] == 'john', data)[0]['age']
gerosalesc
  • 2,983
  • 3
  • 27
  • 46
0

If you need to do this lookup for multiple names, it would be wise to generate a dict with name as a key -

new_dict = {datum['name']: data for datum in data}

new_dict['john']['age']

This way you can easily access it, and seems more pythonic. It might not be the performance optimum solution though, if your data set is too big to be a concern.

hspandher
  • 15,934
  • 2
  • 32
  • 45