# [Python-Dev] Behaviour of max() and min() with equal keys

Jeffrey Yasskin jyasskin at gmail.com
Tue Sep 7 23:47:25 CEST 2010

```On Tue, Sep 7, 2010 at 2:40 PM, Jeffrey Yasskin <jyasskin at gmail.com> wrote:
> On Tue, Sep 7, 2010 at 1:44 PM, Mark Dickinson <dickinsm at gmail.com> wrote:
>> On Tue, Sep 7, 2010 at 8:34 PM, Matthew Woodcraft
>> <matthew at woodcraft.me.uk> wrote:
>>> In CPython, the builtin max() and min() have the property that if there
>>> are items with equal keys, the first item is returned. From a quick look
>>> at their source, I think this is true for Jython and IronPython too.
>>
>> It's actually not clear to me that this behaviour is ideal;  it might
>> make more sense to have max() return the first item among equal
>> largest elements, and min() return the last item.  That way, the
>> special case of two operands has the nice property that (max(x, y),
>> min(x, y)) is always either (x, y) or (y, x), rather than being
>> possibly (x, x) or (y, y).  (That is, id(max(x, y)) and id(min(x, y))
>> are id(x) and id(y) in one order or the other.)
>>
>> The max and min methods for the Decimal module take care to work this
>> way, for example:
>>
>>>>> x, y = Decimal(2), Decimal('2.0')
>>>>> x.max(y), x.min(y)
>> (Decimal('2'), Decimal('2.0'))
>>
>> But:
>>
>>>>> max(x, y), min(x, y)
>> (Decimal('2'), Decimal('2'))
>>
>
> Decimal may actually have this backwards. The idea would be that
> min(*lst) == sorted(lst)[0], and max(*lst) == sorted(lst)[-1]. Given a
> stable sort, then, max of equivalent elements would return the last
> element, and min the first. According to Alex Stepanov, this helps
> some with composing these small order statistics into larger
> stably-ordered functions.
>
> I do think Decimal.max's answer is better than the builtin's answer,
> and that the incremental benefit from returning the last instead of
> first is pretty small.

Actually, Decimal isn't doing anything along these lines. At least in
Python 2.6, I get:

>>> Decimal('2').max(Decimal('2.0'))
Decimal('2')
>>> Decimal('2.0').max(Decimal('2'))
Decimal('2')
>>> Decimal('2.0').min(Decimal('2'))
Decimal('2.0')
>>> Decimal('2').min(Decimal('2.0'))
Decimal('2.0')

indicating that '2' is considered larger than '2.0' in the min/max
comparison. It's ignoring the order of the arguments. It also creates
a new Decimal object for the return value, so I can't use id() to
check which one of identical elements it returns.
```