Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List sorting with multiple attributes and mixed order

Tags:

I have to sort a list with multiple attributes. I can do that in ascending order for ALL attributes easily with

L.sort(key=operator.attrgetter(attribute)).... 

but the problem is, that I have to use mixed configurations for ascending/descending... I have to "imitate" a bit the SQL Order By where you can do something like name ASC, year DESC. Is there a way to do this easily in Python without having to implement a custom compare function?

like image 539
Bernhard Vallant Avatar asked Oct 04 '09 12:10

Bernhard Vallant


People also ask

Can you sort a list with different data types?

Python does not guarantee that the sort() function will work if a list contains items of different data types. As long as the items can be compared using the < comparison operator, an attempt will be made to sort the list. Otherwise, an error or exception may be generated.

How do you sort a list of objects based on an attribute of the objects?

sort() function to sort a collection of objects (using some attribute) in Python. This function sorts the list in-place and produces a stable sort. It accepts two optional keyword-only arguments: key and reverse. The key argument specifies a single-arg function to extract a comparison key from each list object.

What is the difference between sorted and sort in Python?

The sorted() function returns a sorted list of the specific iterable object. The sort() method sorts the list. 2. It sorts the list in ascending order by default.


2 Answers

If your attributes are numeric, you have this.

def mixed_order( a ):     return ( a.attribute1, -a.attribute2 )  someList.sort( key=mixed_order ) 

If your attributes includes strings or other more complex objects, you have some choices.

The .sort() method is stable: you can do multiple passes. This is perhaps the simplest. It's also remarkably fast.

def key1( a ): return a.attribute1 def key2( a ): return a.attribute2  someList.sort( key=key2, reverse=True ) someList.sort( key=key1 ) 

If this is the only sort, you can define your own special-purpose comparison operators. Minimally, you need __eq__ and __lt__. The other four can be derived from these two by simple logic.

like image 115
S.Lott Avatar answered Oct 10 '22 07:10

S.Lott


A custom function will render your code more readable. If you have many sorting operations and you don't want to create those functions though, you can use lambda's:

L.sort(lambda x, y: cmp(x.name, y.name) or -cmp(x.year, y.year)) 
like image 32
RedGlyph Avatar answered Oct 10 '22 06:10

RedGlyph