Welcome, guest | Sign In | My Account | Store | Cart

This class provides objects that can be sorted by multiple keys, with each key independently ascending or descending. The class is designed to replicate the functionality of the SQL 'ORDER BY' clause.

Python, 60 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
###############################################
#
# sqlSortable Class - this class supports sorting of objects using 
#                     the same terms as used when specifying a sort in SQL
#   Andrew M. Henshaw 8/15/01


class sqlSortable:
    def __init__(self, **args):
        self.__dict__.update(args)

    def setSort(self, sortOrder):
        self.sortFields = []
        for text in sortOrder:
            sortBy, direction = (text+' ').split(' ', 1)
            self.sortFields.append((sortBy, direction[0:4].lower() == 'desc'))
    
    def __repr__(self):
        return repr([getattr(self, x) for x, reverse in self.sortFields])
        
    def __cmp__(self, other):
        myFields    = []
        otherFields = []
        for sortBy, reverse in self.sortFields:
            myField, otherField = getattr(self, sortBy), getattr(other, sortBy)
            if reverse:
                myField, otherField = otherField, myField
            myFields.append(myField)
            otherFields.append(otherField)
        return cmp(myFields, otherFields)



def testSqlSortable():
    data = [('Premier', 'Stealth U-11'),('Premier', 'Stealth U-10'),('Premier', 'Stealth U-12'),
            ('Co-ed',   'Cyclones'),    ('Co-ed',   'Lightning'),   ('Co-ed',   'Dolphins'),
            ('Girls',   'Dynamos'),     ('Girls',   'Tigers'),      ('Girls',   'Dolphins')]

    testList = [sqlSortable(program=program, name=name) for program, name in data]

    tests = [['program DESC', 'name'],
             ['name desc', 'program asc']]

    for sortBy in tests:
        print '#### Test basic sorting ###', sortBy
        for sortable in testList:
            sortable.setSort(sortBy)
        testList.sort()
        for item in testList:
            print item
    print '#### Test modification of attributes ###', sortBy
    assert testList[4].name == 'Lightning'
    testList[4].name = 'ZZ 1st name'
    testList.sort()
    for item in testList:
        print item
    

if __name__ == '__main__':
    testSqlSortable()

Occasionally, I need to do database processing that is more complex than can be handled within the SQL framework. With this class, I can extract the database rows and instantiate the class object for each row. After massaging the objects, I apply a list of sort conditions, such as ['name', 'value DESC'] (which would be equivalent to the SQL clause 'ORDER BY name, value DESC') and sort.

The class handles multiple-key, multiple-direction sorts in the __cmp__ method. A list of attributes is built for each key and individual items are swapped between the two objects if that particular key has a reversed sort order.

Created by Andrew Henshaw on Thu, 6 Sep 2001 (PSF)
Python recipes (4591)
Andrew Henshaw's recipes (2)
Python Cookbook Edition 1 (103)

Required Modules

  • (none specified)

Other Information and Tasks