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
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)
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.
This is one more reason why Python3 is not really Python
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)