77

When using the max() function in Python to find the maximum value in a list (or tuple, dict etc.) and there is a tie for maximum value, which one does Python pick? Is it random?

This is relevant if, for instance, one has a list of tuples and one selects a maximum (using a key=) based on the first element of the tuple but there are different second elements. How does Python decide which one to pick as the maximum?

Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
Double AA
  • 5,759
  • 16
  • 44
  • 56
  • 7
    Just don't try to rely on any of this for a sorting function, please. – hugomg Jul 21 '11 at 21:28
  • 1
    See the answer to http://stackoverflow.com/questions/4237914/python-max-min-builtin-functions-depend-on-parameter-order – agf Jul 21 '11 at 21:36
  • 2
    I agree with missingno that this isn't behavior you should rely on. I hope you're just asking for debugging purposes. If you care about the second element of the tuple (in your hypothetical example) then you should always consider it in your key= function. – codewarrior Jul 22 '11 at 01:44
  • @codewarrior sometimes any max will do, but you still want a guarantee that for the same input the same object will be the max. – pfctdayelise Mar 20 '13 at 04:04

5 Answers5

83

It picks the first element it sees. See the documentation for max():

If multiple items are maximal, the function returns the first one encountered. This is consistent with other sort-stability preserving tools such as sorted(iterable, key=keyfunc, reverse=True)[0] and heapq.nlargest(1, iterable, key=keyfunc).

In the source code this is implemented in ./Python/bltinmodule.c by builtin_max, which wraps the more general min_max function.

min_max will iterate through the values and use PyObject_RichCompareBool to see if they are greater than the current value. If so, the greater value replaces it. Equal values will be skipped over.

The result is that the first maximum will be chosen in the case of a tie.

Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
Jeremy
  • 1
  • 85
  • 340
  • 366
22

From empirical testing, it appears that max() and min() on a list will return the first in the list that matches the max()/min() in the event of a tie:

>>> test = [(1, "a"), (1, "b"), (2, "c"), (2, "d")]
>>> max(test, key=lambda x: x[0])
(2, 'c')
>>> test = [(1, "a"), (1, "b"), (2, "d"), (2, "c")]
>>> max(test, key=lambda x: x[0])
(2, 'd')
>>> min(test, key=lambda x: x[0])
(1, 'a')
>>> test = [(1, "b"), (1, "a"), (2, "d"), (2, "c")]
>>> min(test, key=lambda x: x[0])
(1, 'b')

And Jeremy's excellent sleuthing confirms that this is indeed the case.

Community
  • 1
  • 1
Daniel DiPaolo
  • 55,313
  • 14
  • 116
  • 115
17

For Python 3, the behavior of max() in the case of ties is no longer just an implementation detail as detailed in the other answers. The feature is now guaranteed, as the Python 3 docs explicitly state:

If multiple items are maximal, the function returns the first one encountered. This is consistent with other sort-stability preserving tools such as sorted(iterable, key=keyfunc, reverse=True)[0] and heapq.nlargest(1, iterable, key=keyfunc).

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
Chris_Rands
  • 38,994
  • 14
  • 83
  • 119
  • Chris I think my question on meta gained you some well-deserved upvotes :) https://meta.stackoverflow.com/questions/352439/should-we-add-more-explanations-when-closing-as-duplicates – Jean-François Fabre Jul 18 '17 at 08:45
  • 1
    Is there a way to get at the last one encountered, instead of the first one (without having to resort to sorting)? – lifebalance Sep 17 '17 at 11:50
  • 2
    @lifebalance reverse the list before applying max() – Chris_Rands Sep 17 '17 at 14:53
  • @lifebalance Or alternatively [do this](https://stackoverflow.com/questions/17952612/python-finding-the-last-index-of-min-element). (slightly different, that one get the index) – user202729 Jun 21 '18 at 15:24
4

Your question somewhat leads to a note. When sorting a data structure, there is often a desire to keep relative order of objects that are considered equal for the purposes of comparison. This would be known as a stable sort.

If you absolutely needed this feature, you could do a sort(), which will be stable and then have knowledge of the order relative to the original list.

As per python itself, I don't believe that you get any guarantee of which element you will get when you call max(). Other answers are giving the cpython answer, but other implementations (IronPython, Jython) could function differently.

Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
0

For Python 2 versions, IMO, I believe you cannot assume that max() returns the first maximal element in the list in the case of ties. I have this belief because max() is supposed to implement the true mathematical function max, which is used on sets that have a total order, and where elements do not have any "hidden information".

(I will assume that others have researched correctly and the Python documentation does not give any guarantees for max().)

(In general, there are an endless number of questions you can ask about the behavior of a library function, and almost all of them can't be answered. For example: How much stack space will max() use? Will it use SSE? How much temporary memory? Can it compare the same pair of objects more than once (if comparison has a side effect)? Can it run faster than O(n) time for "special" known data structures? etc. etc.)

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
Nayuki
  • 17,911
  • 6
  • 53
  • 80