sort descending on a[1], ascending on a[0]

Manuel M. Garcia mgarcia at cole-switches.com
Thu Oct 10 16:36:23 EDT 2002


t = """

jsaul asked a question about a custom sort, which reminded me of a
problem I often have with sorting.

What is everyones favorite way of sorting descending on a[1], and
ascending on a[0]? (or however you wish, even changing this on
the fly)

I am not a big fan of passing sort() a comparison function, but I
don't see how I could use the Decorate - Sort - Undecorate (DSU)
technique.

Below is how I usually do it, and also a more general method that
generates the function for sort() that lets you choose
the order of the indexes and whether you sort ascending or
descending for each index.

b b b b b b b b h h h h h descending comparison aaaaaaaaaa

"""

import re

t = re.sub(r'[^a-z]+',' ',t.lower()).strip()

d = {}
for w in t.split(' '):
    d[w] = d.get(w,0) + 1

def sort_f(a,b):
    if a[1] != b[1]:
        return -cmp(a[1],b[1])
    else:
        return cmp(a[0],b[0])

list0 = d.items()
list0.sort(sort_f)
print '* sort by a[1](desc) then a[0]'
for a in list0[:10]: print a

# very clean with lexically nested scopes (Python 2.2)
def make_sort_f(list0):
    def f(a,b):
        for (i,m) in list0:
            if a[i] == b[i]: continue
            return m * cmp(a[i],b[i])
        return 0
    return f

list1 = [ (w,c,len(w)) for (w,c) in d.items() ]
list1.sort(make_sort_f( [(2,-1),(1,-1),(0,1)] ))
print '* sort by a[2](desc) then a[1](desc) then a[0]'
for a in list1[:10]: print a

----------(output)-----------

* sort by a[1](desc) then a[0]
('a', 8)
('b', 8)
('h', 5)
('i', 5)
('sort', 5)
('the', 5)
('of', 4)
('and', 3)
('descending', 3)
('on', 3)
* sort by a[2](desc) then a[1](desc) then a[0]
('descending', 3, 10)
('comparison', 2, 10)
('aaaaaaaaaa', 1, 10)
('undecorate', 1, 10)
('ascending', 2, 9)
('everyones', 1, 9)
('generates', 1, 9)
('technique', 1, 9)
('function', 2, 8)
('changing', 1, 8)



More information about the Python-list mailing list