Sorting on multiple values, some ascending, some descending

Christophe chris.cavalaria at free.fr
Thu Jan 4 05:21:27 EST 2007


bearophileHUGS at lycos.com a écrit :
> Raymond Hettinger:
>> The simplest way is to take advantage of sort-stability and do
>> successive sorts.  For example, to sort by a primary key ascending and
>> a secondary key decending:
>>    L.sort(key=lambda r: r.secondary, reverse=True)
>>    L.sort(key=lambda r: r.primary)
> 
> That's probably the faster and simpler way.
> The following solution is probably slow, memory-hungry, and it's not
> tested much so it may be buggy too, but it shows my idea, and bugs can
> be fixed:
> 
> class Inverter:
>     def __init__(self, item, reversed=False):
>             self.item = item
>             self.reversed = reversed
>     def __cmp__(self, other):
>         if self.reversed:
>             return cmp(other.item, self.item)
>         else:
>             return cmp(self.item, other.item)
> 
> data = [[1, "a", "b"], [1, "b", "d"], [1, "d", "a"]]
> reverses = [True, False, False]
> 
> print sorted(data, key=lambda subseq: map(Inverter, subseq, reverses))

Nice trick, but don't get too caught up using classes ;) Try that one 
instead for much better performance :

class Inverter:
     def __init__(self, item):
         self.item = item
     def __cmp__(self, other):
         return cmp(other, self.item)

def invert_if(item, reversed=False):
     if reversed:
         return Inverter(item)
     return item

data = [[1, "a", "b"], [1, "b", "d"], [1, "d", "a"]]
reverses = [True, False, False]

print sorted(data, key=lambda subseq: map(invert_, subseq, reverses))



More information about the Python-list mailing list