How to find the min/max value of a common key in a list of dicts?
Asked Answered
B

6

152

I have a list of dictionaries like so:

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

I want to find the min() and max() prices. Now, I can sort this easily enough using a key with a lambda expression (as found in another Stack Overflow post), so if there is no other way I'm not stuck. However, from what I've seen there is almost always a direct way in Python, so this is an opportunity for me to learn a bit more.

Betts answered 16/3, 2011 at 3:56 Comment(0)
C
384
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'])

This tells you not just what the max price is but also which item is most expensive.

Cherriecherrita answered 16/3, 2011 at 14:20 Comment(6)
Ah, that's a nice touch, returning the entire item. Not needed in this instance, but very definitely a keeper for the future.Betts
How would you do this to find the largest 5 items in a list? (not just the max)Fund
@Fund You could sort and then select the top 5? see #73399Leavitt
@Hugh Bothwell This is magical! Can you help me find the resources to explain this? Thanks!Cyclist
This works perfectly. Following @thomas.mac's comment , is there an easy way to get all the minima if there are several (as a list of matching dict, for instance) ?Greensand
How would you make sure that ['price'] exists in the dict?Candler
M
75

There are several options. Here is a straight-forward one:

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

[Edit]

If you only wanted to iterate through the list once, you could try this (assuming the values could be represented as 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)
Montherlant answered 16/3, 2011 at 4:1 Comment(4)
I accept this as the answer as it not only gives the answer, but it also showed me that one can abstract sequences. Darn, Python is a beautiful language. Thanks!Betts
If you don't need the seq, and the list is large, this can be inefficient since the memory for the entire list has to be allocated just to find the max.Sizar
It throws AttributeError: module 'sys' has no attribute 'maxint'Sprit
@Sprit in Python 3, sys.maxint has changed to sys.maxsizeMaestricht
D
55

I think the most direct (and most Pythonic) expression would be something like:

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

This avoids the overhead of sorting the list -- and, by using a generator expression, instead of a list comprehension -- actually avoids creating any lists, as well. Efficient, direct, readable... Pythonic!

Distich answered 16/3, 2011 at 4:0 Comment(0)
O
15

One answer would be mapping your dicts to the value of interest inside a generator expression, and then applying the built-ins min and max.

myMax = max(d['price'] for d in myList)
myMin = min(d['price'] for d in myList)
Orobanchaceous answered 16/3, 2011 at 4:0 Comment(2)
nitpick: those are generator expressions. List comprehensions are surrounded by [ and ], and actually generate a Python list as an intermediate step.Distich
@dcrosta, yes, thank you, you're right of course. I changed the wording since that was embarrassing.Orobanchaceous
C
5

can also use this:

from operator import itemgetter

lst = [{'price': 99, 'barcode': '2342355'}, {'price': 88, 'barcode': '2345566'}]  
max(map(itemgetter('price'), lst))
Chaplin answered 30/9, 2018 at 6:23 Comment(0)
M
0

And to add to this great page: the top answer in a generic convenient function:


def takeMaxFromDictList(listOfDicts: list, keyToLookAt: str) -> dict:
  return max( listOfDicts, key=lambda x: x[keyToLookAt] )

# -------------------------------------------------------------------

examplelist = [{'score': 0.995, 'label': 'buildings'},
               {'score': 0.002, 'label': 'mountain'},
               {'score': 0.001, 'label': 'forest'}]
 
print ( takeMaxFromDictList(examplelist, 'score') )

>>> {'score': 0.995, 'label': 'buildings'}

Monck answered 2/10, 2023 at 21:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.