306

I have a list of dicts like this:

[{'value': 'apple', 'blah': 2}, 
 {'value': 'banana', 'blah': 3} , 
 {'value': 'cars', 'blah': 4}]

I want ['apple', 'banana', 'cars']

Whats the best way to do this?

Georgy
  • 12,464
  • 7
  • 65
  • 73
SuperString
  • 21,593
  • 37
  • 91
  • 122

10 Answers10

517

Assuming every dict has a value key, you can write (assuming your list is named l)

[d['value'] for d in l]

If value might be missing, you can use

[d['value'] for d in l if 'value' in d]
Ismail Badawi
  • 36,054
  • 7
  • 85
  • 97
  • 12
    To treat missing value for a key, one may also use d.get("key_to_lookup", "alternate_value"). Then, it will look like: [d.get('value', 'alt') for d in l] . If value is not present as key, it will simply return 'alt'. – abhinav Feb 04 '18 at 18:46
  • This "magic" is known as list comprehension https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions – William Ardila Mar 22 '20 at 02:58
  • Life Saver! I have been trying/searching this for sqlalchemy objects since long. Now it worked like ```[d.value for d in l]``` thank you :) – krupesh Anadkat Jul 20 '20 at 17:24
  • It'll be `d['Value']` instead of `d['value']`. – Rafiq Apr 04 '22 at 12:40
60

Here's another way to do it using map() and lambda functions:

>>> map(lambda d: d['value'], l)

where l is the list. I see this way "sexiest", but I would do it using the list comprehension.

Update: In case that 'value' might be missing as a key use:

>>> map(lambda d: d.get('value', 'default value'), l)

Update: I'm also not a big fan of lambdas, I prefer to name things... this is how I would do it with that in mind:

>>> import operator
>>> get_value = operator.itemgetter('value')
>>> map(get_value, l)

I would even go further and create a sole function that explicitly says what I want to achieve:

>>> import operator, functools
>>> get_value = operator.itemgetter('value')
>>> get_values = functools.partial(map, get_value)
>>> get_values(l)
... [<list of values>]

With Python 3, since map returns an iterator, use list to return a list, e.g. list(map(operator.itemgetter('value'), l)).

Anler
  • 1,793
  • 13
  • 21
26
[x['value'] for x in list_of_dicts]
Michał Trybus
  • 11,526
  • 3
  • 30
  • 42
  • or [d.getkey('value') for d in dict_list] – rplnt Sep 01 '11 at 14:10
  • 4
    @rpInt Um, there is no such thing as `getkey`.. do you mean `d.get('value')`? That would be the same as @isbadawi's 2nd list comprehension, not Michal's. – agf Sep 01 '11 at 14:18
  • 4
    Yes, sorry, I meant get. And I meant it as something that won't throw exception if key is missing. But @isbadawi's solution is better as get() will supply None (or whatever we specify as default) when the key is missing. – rplnt Sep 01 '11 at 15:04
6

For a very simple case like this, a comprehension, as in Ismail Badawi's answer is definitely the way to go.

But when things get more complicated, and you need to start writing multi-clause or nested comprehensions with complex expressions in them, it's worth looking into other alternatives. There are a few different (quasi-)standard ways to specify XPath-style searches on nested dict-and-list structures, such as JSONPath, DPath, and KVC. And there are nice libraries on PyPI for them.

Here's an example with the library named dpath, showing how it can simplify something just a bit more complicated:

>>> dd = {
...     'fruits': [{'value': 'apple', 'blah': 2}, {'value': 'banana', 'blah': 3}],
...     'vehicles': [{'value': 'cars', 'blah':4}]}

>>> {key: [{'value': d['value']} for d in value] for key, value in dd.items()}
{'fruits': [{'value': 'apple'}, {'value': 'banana'}],
 'vehicles': [{'value': 'cars'}]}

>>> dpath.util.search(dd, '*/*/value')
{'fruits': [{'value': 'apple'}, {'value': 'banana'}],
 'vehicles': [{'value': 'cars'}]}

Or, using jsonpath-ng:

>>> [d['value'] for key, value in dd.items() for d in value]
['apple', 'banana', 'cars']
>>> [m.value for m in jsonpath_ng.parse('*.[*].value').find(dd)]
['apple', 'banana', 'cars']

This one may not look quite as simple at first glance, because find returns match objects, which include all kinds of things besides just the matched value, such as a path directly to each item. But for more complex expressions, being able to specify a path like '*.[*].value' instead of a comprehension clause for each * can make a big difference. Plus, JSONPath is a language-agnostic specification, and there are even online testers that can be very handy for debugging.

abarnert
  • 354,177
  • 51
  • 601
  • 671
6

I think as simple as below would give you what you are looking for.

In[5]: ll = [{'value': 'apple', 'blah': 2}, {'value': 'banana', 'blah': 3} , {'value': 'cars', 'blah':4}]
In[6]: ld = [d.get('value', None) for d in ll]
In[7]: ld
Out[7]: ['apple', 'banana', 'cars']

You can do this with a combination of map and lambda as well but list comprehension looks more elegant and pythonic.

For a smaller input list comprehension is way to go but if the input is really big then i guess generators are the ideal way.

In[11]: gd = (d.get('value', None) for d in ll)
In[12]: gd
Out[12]: <generator object <genexpr> at 0x7f5774568b10>
In[13]: '-'.join(gd)
Out[13]: 'apple-banana-cars'

Here is a comparison of all possible solutions for bigger input

 In[2]: l = [{'value': 'apple', 'blah': 2}, {'value': 'banana', 'blah': 3} , {'value': 'cars', 'blah':4}] * 9000000
In[3]: def gen_version():
  ...:     for i in l:
  ...:         yield i.get('value', None)
  ...: 
In[4]: def list_comp_verison():
  ...:     return [i.get('value', None) for i in l]
  ...: 
In[5]: def list_verison():
  ...:     ll = []
  ...:     for i in l:
  ...:         ll.append(i.get('value', None))
  ...:     return ll
In[10]: def map_lambda_version():
   ...:      m = map(lambda i:i.get('value', None), l)
   ...:      return m
   ...: 
In[11]: %timeit gen_version()
172 ns ± 0.393 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In[12]: %timeit map_lambda_version()
203 ns ± 2.31 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In[13]: %timeit list_comp_verison()
1.61 s ± 20.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In[14]: %timeit list_verison()
2.29 s ± 4.58 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

As you can see, generators are a better solution in comparison to the others, map is also slower compared to generator for reason I will leave up to OP to figure out.

epsilon
  • 2,849
  • 16
  • 23
Rohit
  • 3,659
  • 3
  • 35
  • 57
6

Using list comprehension

input:

d = [{'value': 'apple', 'blah': 2}, {'value': 'banana', 'blah': 3}, {'value': 'cars', 'blah': 4}]
    
        
values = [i['value'] for i in d]

print(values)

Output:

['apple', 'banana', 'cars']
Ramineni Ravi Teja
  • 3,568
  • 26
  • 37
2

Follow the example --

songs = [
{"title": "happy birthday", "playcount": 4},
{"title": "AC/DC", "playcount": 2},
{"title": "Billie Jean", "playcount": 6},
{"title": "Human Touch", "playcount": 3}
]

print("===========================")
print(f'Songs --> {songs} \n')
title = list(map(lambda x : x['title'], songs))
print(f'Print Title --> {title}')

playcount = list(map(lambda x : x['playcount'], songs))
print(f'Print Playcount --> {playcount}')
print (f'Print Sorted playcount --> {sorted(playcount)}')

# Aliter -
print(sorted(list(map(lambda x: x['playcount'],songs))))
Mohan. A
  • 419
  • 4
  • 13
-1

Get key values from list of dictionaries in python?

  1. Get key values from list of dictionaries in python?

Ex:

data = 
[{'obj1':[{'cpu_percentage':'15%','ram':3,'memory_percentage':'66%'}]},
{'obj2': [{'cpu_percentage':'0','ram':4,'memory_percentage':'35%'}]}]

for d in data:

  for key,value in d.items(): 

      z ={key: {'cpu_percentage': d['cpu_percentage'],'memory_percentage': d['memory_percentage']} for d in value} 
      print(z)

Output:

{'obj1': {'cpu_percentage': '15%', 'memory_percentage': '66%'}}
{'obj2': {'cpu_percentage': '0', 'memory_percentage': '35%'}}
whoami - fakeFaceTrueSoul
  • 17,086
  • 6
  • 32
  • 46
Kalyani B
  • 7
  • 2
-3

Please try out this one.

d =[{'value': 'apple', 'blah': 2},  {'value': 'banana', 'blah': 3} , {'value': 
'cars', 'blah': 4}] 
b=d[0]['value']
c=d[1]['value']
d=d[2]['value']
new_list=[b,c,d]
print(new_list)

Output:

['apple', 'banana', 'cars']
fireball.1
  • 1,413
  • 2
  • 17
  • 42
-4

A very simple way to do it is:

list1=['']
j=0
for i in com_list:
    if j==0:
        list1[0]=(i['value'])
    else:
        list1.append(i['value'])
    j+=1

Output:

['apple', 'banana', 'cars']

Maelig
  • 2,046
  • 4
  • 24
  • 49
Ayushi
  • 1
  • 1