views:

124

answers:

2

I need to sort a list of tuples by first item in descending order, and then by second item in ascending order.

To do this, I have implemented the following function, but I think it could be faster.

>>> compare = lambda a, b: -cmp(b[1], a[1]) if b[0] == a[0] else cmp(b[0], a[0])
>>> sorted([(0, 2), (0, 1), (1, 0), (1, 2)], cmp=compare)
[(1, 0), (1, 2), (0, 1), (0, 2)]

Is it possible to optimize it? See the comparison against the built-in function:

>>> timeit.Timer(stmt='sorted([(int(random.getrandbits(4)),int(random.getrandbits(4))) for x in xrange(10)], cmp=compare)', setup='import random; compare=compare = lambda a, b: -cmp(b[1], a[1]) if b[0] == a[0] else cmp(b[0], a[0])').timeit(100000)
4.0584850867917339
>>> timeit.Timer(stmt='sorted([(int(random.getrandbits(4)),int(random.getrandbits(4))) for x in xrange(10)])', setup='import random').timeit(100000)
2.6582965153393161
+7  A: 

For me, it is a little faster to use a key instead of a comparison function, and arguably also easier to read:

sorted([(0, 2), (0, 1), (1, 0), (1, 2)], key = lambda x:(-x[0], x[1]))

This requires Python 2.4 or newer.

Mark Byers
+1, you beat me. Comes in about half way between the OP's timing tests.
balpha
+1 added an end paren.
Adam Bernier
Thank you! This is fast enough for me :-)>>>timeit.Timer(stmt='sorted([(int(random.getrandbits(4)),int(random.getrandbits(4))) for x in xrange(10)], key = lambda x:(-x[0], x[1]))', setup='import random;').timeit(100000)3.2802747276537048
jbochi
A: 

How does this stack up for you?

compare = lambda a, b: cmp(b[0], a[0]) and cmp(a[1],b[1])
Paul McGuire