Dans List of Dicts, recherchez la valeur min () d'un champ Dict commun

91

J'ai une liste de dictionnaires comme ceci:

[{'price': 99, 'barcode': '2342355'}, {'price': 88, 'barcode': '2345566'}]

Je veux trouver les prix min () et max (). Maintenant, je peux trier cela assez facilement en utilisant une clé avec une expression lambda (comme trouvé dans un autre article SO), donc s'il n'y a pas d'autre moyen, je ne suis pas coincé. Cependant, d'après ce que j'ai vu, il y a presque toujours un moyen direct en Python, c'est donc l'occasion pour moi d'en apprendre un peu plus.

Hank Fay
la source

Réponses:

60

Il existe plusieurs options. En voici une simple:

seq = [x['the_key'] for x in dict_list]
min(seq)
max(seq)

[Éditer]

Si vous ne souhaitez parcourir la liste qu'une seule fois, vous pouvez essayer ceci (en supposant que les valeurs puissent être représentées par ints):

import sys

lo,hi = sys.maxint,-sys.maxint-1
for x in (item['the_key'] for item in dict_list):
    lo,hi = min(x,lo),max(x,hi)
dappawit
la source
J'accepte cela comme la réponse car non seulement cela donne la réponse, mais cela m'a aussi montré que l'on peut abstraire des séquences. Darn, Python est un beau langage. Merci!
Hank Fay
2
Si vous n'avez pas besoin de seq, et que la liste est grande, cela peut être inefficace car la mémoire de la liste entière doit être allouée uniquement pour trouver le maximum.
Charles L.
Il jetteAttributeError: module 'sys' has no attribute 'maxint'
Suncatcher
229
lst = [{'price': 99, 'barcode': '2342355'}, {'price': 88, 'barcode': '2345566'}]

maxPricedItem = max(lst, key=lambda x:x['price'])
minPricedItem = min(lst, key=lambda x:x['price'])

Cela vous indique non seulement quel est le prix maximum, mais également quel article est le plus cher.

Hugh Bothwell
la source
4
Ah, c'est une bonne idée de retourner l'article entier. Pas nécessaire dans ce cas, mais très certainement un gardien pour l'avenir.
Hank Fay
c'est ce que je cherchais. Impressionnant. Merci!
svenwildermann
Une solution élégante!
anapaulagomes
2
@ thomas.mac Vous pouvez trier puis sélectionner le top 5? voir stackoverflow.com/questions/72899/…
hibernado
2
Cela fonctionne parfaitement. Suite au commentaire de @ thomas.mac, y a-t-il un moyen simple d'obtenir tous les minima s'il y en a plusieurs (comme une liste de dict correspondants, par exemple)?
Romain le
40

Je pense que l'expression la plus directe (et la plus pythonique) serait quelque chose comme:

min_price = min(item['price'] for item in items)

Cela évite la surcharge de tri de la liste - et, en utilisant une expression de générateur, au lieu d'une compréhension de liste - évite également de créer des listes. Efficace, direct, lisible ... Pythonique!

dcrosta
la source
8

Une réponse serait de mapper vos dictats sur la valeur d'intérêt dans une expression de générateur, puis d'appliquer les éléments intégrés minet max.

myMax = max(d['price'] for d in myList)
myMin = min(d['price'] for d in myList)
rlibby
la source
nitpick: ce sont des expressions génératrices. Les compréhensions de liste sont entourées de [et ]et génèrent en fait une liste Python comme étape intermédiaire.
dcrosta
@dcrosta, oui, merci, vous avez raison bien sûr. J'ai changé le libellé car c'était embarrassant.
rlibby
3

peut également utiliser ceci:

from operator import itemgetter

lst = [{'price': 99, 'barcode': '2342355'}, {'price': 88, 'barcode': '2345566'}]  
max(map(itemgetter('price'), lst))
carton.swing
la source