Because this bit me harder than I was ready for, I thought I'd make a note of it for the next victim.

In Python 2, suppose you have this:


Python 2.7.5
>>> items = [(1, 'A number'), ('a', 'A letter'), (2, 'Another number')]

Sorting them, without specifying how, will automatically notice that it contains tuples:


Python 2.7.5
>>> sorted(items)
[(1, 'A number'), (2, 'Another number'), ('a', 'A letter')]

This doesn't work in Python 3 because comparing integers and strings is not allowed. E.g.:


Python 3.3.3
>>> 1 < '1'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: int() < str()

You have to convert them to stings first.


Python 3.3.3
>>> sorted(items, key=lambda x: str(x[0]))
[(1, 'A number'), (2, 'Another number'), ('a', 'A letter')]

If you really need to sort by 1 < '1' this won't work. Then you need a more complex key function. E.g.:


Python 3.3.3
>>> def keyfunction(x):
...   v = x[0]
...   if isinstance(v, int): v = '0%d' % v
...   return v
...
>>> sorted(items, key=keyfunction)
[(1, 'A number'), (2, 'Another number'), ('1', 'Actually a string')]

That's really messy but the best I can come up with at past 4PM on Friday.

Comments

Joseph G. Mitzen

Nice solution! I guess you could make it even messier with a lambda:

sorted(items, key=lambda item: ('' if isinstance(item[0], int) else '0',)+item)

Steve Fink

Or use a tuple as a key:

  sorted(items, key=lambda x: (isinstance(x[0], str), x[0]))

but it seems like it'd be better to not have mixed types in the first place.

Philippe Ombredanne

This is one more reason why Python3 is not really Python

Nicolas

What about integer to tuple comparison?
Python 2 could sort the following, while Python 3 could not. Any suggestions are appreciated.

(1, (11, 8, 7, 6, 2)) # high card 11 (rank5)
(1, (12, 11, 8, 7, 2)) # high card 12 (rank4)
((3, 2), (11, 12)) # full house (triple and pair) (rank1)
((2, 1, 1, 1), (12, 11, 7, 6)) # pair of 12 (rank3)
((3, 1, 1), (12, 6, 3)) # three of 12 (rank2)

Your email will never ever be published.

Related posts