46

I have a list like this:

alkaline_earth_values = [['beryllium',  4], 
                         ['magnesium', 12],
                         ['calcium',   20],
                         ['strontium', 38], 
                         ['barium',    56], 
                         ['radium',    88]]

If I simply use the max(list) method, it will return the answer 'strontium', which would be correct if I was trying to find the max name, however I'm trying to return the element whose integer is highest.

Nicolas Gervais
  • 33,817
  • 13
  • 115
  • 143
davelupt
  • 1,845
  • 4
  • 21
  • 32
  • 3
    The answers here are perfectly good, but it may also be worth checking out [a similar question](http://stackoverflow.com/questions/14884220/search-the-biggest-number-of-one-column-in-a-list-of-list-python#14884336), which was closed as being a duplicate of this one but nevertheless has some useful answers that are not the same as these. – John Y Feb 14 '13 at 21:44
  • `max(alkaline_earth_values)` actually returns `['strontium', 38]`, so it's giving you both the name and value _pair_ with the maximum value. – martineau Nov 04 '18 at 16:30

5 Answers5

84
max(alkaline_earth_values, key=lambda x: x[1])

The reason this works is because the key argument of the max function specifies a function that is called when max wants to know the value by which the maximum element will be searched. max will call that function for each element in the sequence. And lambda x: x[1] creates a small function which takes in a list and returns the first (counting starts from zero) element. So

k = lambda x: x[1]

is the same as saying

def k(l):
  return l[1]

but shorter and nice to use in situations like this.

martineau
  • 119,623
  • 25
  • 170
  • 301
kynnysmatto
  • 3,665
  • 23
  • 29
  • Would you mind explaining in laymen's terms what this is doing. I think I understand that the x: x[1] defines the position, because if I substitute in 0 for 1 it returns the correct max string value. But, however I do not completely understand the point of key and lambda despite looking at the Python library. – davelupt Jan 26 '11 at 00:54
  • 1
    key is a keyword argument to the max() builtin function. The key argument should be a callable (function, lambda, etc.) that given an element of the iterable returns a value for use in comparison. The "lambda x: x[1]" creates an anonymous function (lambda) that returns the second element of something that supports the Python slice notation. – Spike Gronim Jan 26 '11 at 00:58
  • So if I had another level of nesting in a list like alkaline_earth_values = [['beryllium', 4,['a' ,1]],['magnesium', 12, ['b',2]],['calcium', 20,['c', 3]],['strontium', 38 ['d', 4]],['barium', 56['e', 5]], ['radium', 88['f', 1]]] Would I do max(alkaline_earth_metals, key = lambda x:x[4] in order to sort by the triple nested integer? – davelupt Jan 26 '11 at 01:03
  • 1
    You mean by the values 1,2,3,4,5,1? In that case you would do: key=lambda x: x[2][1]. Because you would first be taking the 2nd element of ['beryllium', 4, [a, 1]] which would be [a, 1]. And then you would continue by taking the 1st element of that list, which would be 1. – kynnysmatto Jan 26 '11 at 01:09
  • or would it be print(max(alkaline_earth_metals, key=lambda x: x[2][1])) – davelupt Jan 26 '11 at 01:12
  • I've been working with a team who only recently switched to Python and I saw how easy it is to get confused by using max() with nested sequences. I ended up writing a tutorial to do a bit of a deep dive into how the default sorting behavior can be modified, maybe this helps someone out: https://dbader.org/blog/python-min-max-and-nested-lists – dbader Jul 26 '16 at 10:01
  • If multiple lists have the same value as an element. How would `lambda` or `itemgetter` get them? – user977828 Nov 12 '20 at 20:42
8

Use the key argument.

max(alk..., key=operator.itemgetter(1))
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • 1
    If multiple lists have the same value as an element. How would `lambda` print the duplications out? – user977828 Nov 12 '20 at 20:58
  • @user977828 it requires a second iteration, e.g. `m = max(alkaline_earth_values, key=operator.itemgetter(1)); [item for item in alkaline_earth_values if item[1] == m[1]]` – Chris_Rands Jan 02 '22 at 18:04
0

it is rather tricky to assume that an item in a list is actually still a number. If the numbers have become strings, the max() will return the 'value' with the highest first number:

alkaline_earth_values = [['beryllium', '9'], ['magnesium', '12'],['calcium', '20'],
                         ['strontium', '38'], ['barium', '56'], ['radium', '88']]
max(alkaline_earth_values, key=lambda x: x[1])

returns ['beryllium', '9']

max(alkaline_earth_values, key=lambda x: float(x[1]))

will do the trick, when you are sure it will be a number

brooksrelyt
  • 3,925
  • 5
  • 31
  • 54
uytda
  • 83
  • 1
  • 8
0

For high speed consider pandas or numpy:

Import pandas as pd
alkaline_earth_values = [['beryllium', 4], ['magnesium', 12],['calcium', 20],
                     ['strontium', 38], ['barium', 56], ['radium', 88]]
pd.DataFrame(alkaline_earth_values)[1].max()
Peter Mølgaard Pallesen
  • 1,470
  • 1
  • 15
  • 26
0

You could convert your list of lists to a Counter and the call the .most_common() method. This easily allow you to find the maximum or top n values:

>>> from collections import Counter
>>> Counter(dict(alkaline_earth_values)).most_common(1)
[('radium', 88)]
>>> Counter(dict(alkaline_earth_values)).most_common(3)
[('radium', 88), ('barium', 56), ('strontium', 38)]
Chris_Rands
  • 38,994
  • 14
  • 83
  • 119