sorting ascending/descending with operator.attrgetter

Peter Otten __peter__ at web.de
Wed Mar 31 13:49:08 EDT 2010


Chris Curvey wrote:

> I must be having a brain cramp.  Given a list of objects, how can I
> sort the list on one attribute in descending order, then sort within
> each group in ascending order on another attribute.
> 
> For example:
> 
> class Foo:
>     def __init__(self, a, b, c):
>         self.a = a
>         self.b = b
>         self.c = c
> 
> 
> I can do "allmyfoos.sort(operator.attrgetter('a','b'))" to sort
> ascending on both attributes, but how could i sort by "a, descending,
> then b, ascending)?"

In the general case you have to sort twice:

>>> from collections import namedtuple
>>> Foo = namedtuple("Foo", "a b")
>>> items = [Foo(x, y) for x in range(3) for y in range(3)]
>>> def show(items):
...     for item in items: print item
...
>>> show(items)
Foo(a=0, b=0)
Foo(a=0, b=1)
Foo(a=0, b=2)
Foo(a=1, b=0)
Foo(a=1, b=1)
Foo(a=1, b=2)
Foo(a=2, b=0)
Foo(a=2, b=1)
Foo(a=2, b=2)
>>> from operator import attrgetter
>>> items.sort(key=attrgetter("b"))
>>> items.sort(key=attrgetter("a"), reverse=True)
>>> show(items)
Foo(a=2, b=0)
Foo(a=2, b=1)
Foo(a=2, b=2)
Foo(a=1, b=0)
Foo(a=1, b=1)
Foo(a=1, b=2)
Foo(a=0, b=0)
Foo(a=0, b=1)
Foo(a=0, b=2)

This is guaranteed to work because list.sort() is "stable", i. e. it doesn't 
alter the order of items with equal keys.

Peter



More information about the Python-list mailing list