Obtenir une liste de valeurs à partir d'une liste de dictés

185

J'ai une liste de dictionnaires comme celui-ci:

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

Je voudrais ['apple', 'banana', 'cars']

Quelle est la meilleure façon de procéder?

SuperString
la source

Réponses:

326

En supposant que chaque dict a une valueclé, vous pouvez écrire (en supposant que votre liste est nommée l)

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

S'il valuemanque, vous pouvez utiliser

[d['value'] for d in l if 'value' in d]
Ismail Badawi
la source
8
Pour traiter la valeur manquante d'une clé, on peut également utiliser d.get ("key_to_lookup", "alternative_value"). Ensuite, cela ressemblera à: [d.get ('value', 'alt') for d in l]. Si la valeur n'est pas présente comme clé, elle retournera simplement «alt».
abhinav le
Merci pour la solution
Ajay Kumar
Cette "magie" est connue sous le nom de compréhension de liste docs.python.org/3/tutorial
William Ardila
Life Saver! J'essaye / recherche ceci pour les objets sqlalchemy depuis longtemps. Maintenant, cela a fonctionné comme [d.value for d in l]merci :)
Krupesh Anadkat
34

Voici une autre façon de le faire en utilisant les fonctions map () et lambda:

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

où l est la liste. Je vois cette façon "sexy", mais je le ferais en utilisant la compréhension de liste.

Mise à jour: au cas où cette «valeur» serait manquante comme clé, utilisez:

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

Mise à jour: Je ne suis pas non plus un grand fan de lambdas, je préfère nommer les choses ... voici comment je le ferais dans cet esprit:

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

J'irais même plus loin et créerais une fonction unique qui dit explicitement ce que je veux réaliser:

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

Avec Python 3, puisque maprenvoie un itérateur, utilisez listpour renvoyer une liste, par exemple list(map(operator.itemgetter('value'), l)).

Anler
la source
1
Brut! La compréhension de la liste a beaucoup plus de sens ici.
Mike Graham
4
Si vous comptez utiliser le premier map, utilisez operator.itemgetter('value'), pas a lambda.
agf
18
[x['value'] for x in list_of_dicts]
Michał Trybus
la source
ou [d.getkey ('value') pour d dans dict_list]
rplnt
1
@rpInt Um, il n'y a rien de tel que getkey.. tu veux dire d.get('value')? Ce serait la même chose que la deuxième compréhension de la liste de @ isbadawi, pas celle de Michal.
agf
3
Oui, désolé, je voulais dire obtenir. Et je l'ai voulu dire comme quelque chose qui ne lèvera pas d'exception si la clé est manquante. Mais la solution de @ isbadawi est meilleure car get () fournira None (ou ce que nous spécifions par défaut) lorsque la clé est manquante.
rplnt le
5

Pour un cas très simple comme celui-ci, une compréhension, comme dans la réponse d'Ismail Badawi est définitivement la voie à suivre.

Mais lorsque les choses se compliquent et que vous devez commencer à écrire des compréhensions multi-clauses ou imbriquées avec des expressions complexes, cela vaut la peine de chercher d'autres alternatives. Il existe plusieurs méthodes (quasi) standard différentes pour spécifier des recherches de style XPath sur des structures dictées et listes imbriquées, telles que JSONPath, DPath et KVC. Et il y a de belles bibliothèques sur PyPI pour eux.

Voici un exemple avec la bibliothèque nommée dpath, montrant comment cela peut simplifier quelque chose d'un peu plus compliqué:

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

Ou, en utilisant 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']

Celui-ci peut ne pas sembler aussi simple à première vue, car findrenvoie des objets de correspondance, qui incluent toutes sortes de choses en plus de la valeur correspondante, comme un chemin directement vers chaque élément. Mais pour des expressions plus complexes, être capable de spécifier un chemin comme '*.[*].value'au lieu d'une clause de compréhension pour chacune *peut faire une grande différence. De plus, JSONPath est une spécification indépendante du langage, et il existe même des testeurs en ligne qui peuvent être très utiles pour le débogage.

Abarnert
la source
1

Je pense aussi simple que ci-dessous vous donnerait ce que vous recherchez.

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

Vous pouvez le faire avec une combinaison de mapet lambda, mais la compréhension de la liste semble plus élégante et pythonique.

Pour une plus petite compréhension de la liste d'entrée est la voie à suivre, mais si l'entrée est vraiment grande, je suppose que les générateurs sont le moyen idéal.

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'

Voici une comparaison de toutes les solutions possibles pour une contribution plus importante

 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)

Comme vous pouvez le voir, les générateurs sont une meilleure solution par rapport aux autres, la carte est également plus lente que le générateur pour une raison que je laisserai à OP le soin de comprendre.

Rohit
la source
1

Suivre l'exemple --

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. UNE
la source
1

Obtenir les valeurs clés de la liste des dictionnaires en python?

  1. Obtenir les valeurs clés de la liste des dictionnaires en python?

Ex:

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

pour d dans les données:

  for key,value in d.items(): 

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

Production:

{'obj1': {'cpu_percentage': '15%', 'memory_percentage': '66%'}}
{'obj2': {'cpu_percentage': '0', 'memory_percentage': '35%'}}
Kalyani B
la source
-2

Une façon très simple de le faire est:

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

Production:

['pomme', 'banane', 'voitures']

Ayushi
la source