Getting a list of values from a list of dicts

PythonListDictionary

Python Problem Overview


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?

Python Solutions


Solution 1 - Python

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]

Solution 2 - Python

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)).

Solution 3 - Python

[x['value'] for x in list_of_dicts]

Solution 4 - Python

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.

Solution 5 - Python

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.

Solution 6 - Python

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))))

Solution 7 - Python

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%'}}

Solution 8 - Python

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']

Solution 9 - Python

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']

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSuperStringView Question on Stackoverflow
Solution 1 - PythonIsmail BadawiView Answer on Stackoverflow
Solution 2 - PythonAnlerView Answer on Stackoverflow
Solution 3 - PythonMichał TrybusView Answer on Stackoverflow
Solution 4 - PythonabarnertView Answer on Stackoverflow
Solution 5 - PythonRohitView Answer on Stackoverflow
Solution 6 - PythonMohan. AView Answer on Stackoverflow
Solution 7 - PythonKalyani BView Answer on Stackoverflow
Solution 8 - PythonPooja SaiView Answer on Stackoverflow
Solution 9 - PythonAyushiView Answer on Stackoverflow