Sorting a list with entries of unequal types

MRAB python at mrabarnett.plus.com
Fri Jan 29 01:56:55 CET 2010


Ben Finney wrote:
> Howdy all,
> 
> Python 2.6 tells me that, in Python 3, sorting a list with entries of
> incompatible types is not allowed:
> 
> =====
> $ python2.5 -c "foo = [1, True, 'green', 4, -27, 15.3]; foo.sort(); print foo;"
> [-27, 1, True, 4, 15.300000000000001, 'green']
> 
> $ python2.6 -c "foo = [1, True, 'green', 4, -27, 15.3]; foo.sort(); print foo;"
> [-27, 1, True, 4, 15.300000000000001, 'green']
> 
> $ python2.6 -3 -c "foo = [1, True, 'green', 4, -27, 15.3]; foo.sort(); print foo;"
> -c:1: DeprecationWarning: comparing unequal types not supported in 3.x
> [-27, 1, True, 4, 15.300000000000001, 'green']
> =====
> 
> So how should I be sorting a list with entries of “unequal types” such
> that it will work in Python 3?
> 
First you need to decide how they should be ordered, for example by name
of class then value.

Then make tuple keys for the values. Python compares tuple members
one by one, only looking at the next members if the current members are
equal, so if the first members are the class names (str) and the second
members are the values (possibly unequal types), then Python will
compare the values only if the types are the same.

 >>> sorted([1, True, 'green', 4, -27, 15.3], key=lambda value: 
(type(value).__name__, value))
[True, 15.3, -27, 1, 4, 'green']

This does mean that Boolean < float < int, but that's easy to fix:

 >>> def make_key(value):
...     if isinstance(value, (int, float)):
...         return "float", float(value)
...     return type(value).__name__, value
...
 >>> sorted([1, True, 'green', 4, -27, 15.3], key=make_key)
[-27, 1, True, 4, 15.3, 'green']



More information about the Python-list mailing list