Sorting on multiple values, some ascending, some descending

Carsten Haese carsten at uniqsys.com
Wed Jan 3 14:43:01 EST 2007


On Wed, 2007-01-03 at 10:48 -0800, dwelden wrote:
> I have successfully used the sort lambda construct described in
> http://mail.python.org/pipermail/python-list/2006-April/377443.html.
> However, how do I take it one step further such that some values can be
> sorted ascending and others descending? Easy enough if the sort values
> are numeric (just negate the value), but what about text?
> 
> Is the only option to define an external sorting function to loop
> through the list and perform the comparisons one value at a time?

If by "external sorting function" you mean a custom comparison function
to pass to sort as the cmp argument, then that's one option, but not the
only one.

If you know in advance which columns contain strings, you could write a
function that operates on strings and is strictly monotonically
decreasing, i.e. it behaves such that f(x) < f(y) if and only if x > y.
This function could then be used in the sort key for sorting on a string
column in descending order. The following function does the trick:

def antistring(x):
   return [256-ord(c) for c in x]+[257]

(Proof by vigorous handwaving.)

Lastly, if your array is small enough that you can tolerate the
performance hit of multiple passes, you could exploit the fact that
sort() is guaranteed to be stable in sufficiently recent releases of
CPython. Split your sort on n columns into n separate sorts on a single
column each, and use the 'reverse' parameter to specify whether to sort
forward or backwards.

Hope this helps,

Carsten.





More information about the Python-list mailing list