#pragma section-numbers off

= Sorting Lists of Dictionaries =

Frequently you want to sort a list of dictionaries, based on some particular key.

For example:

{{{
#!python
a = {"key1": 5 , "key2": 8, "key3": 2}
b = {"key1": 7 , "key2": 4, "key3": 9}
c = {"key1": 6 , "key2": 1, "key3": 1}
undecorated = [a, b, c] # how do you sort this list?
}}}

There are many ways to do this. Here's the fastest way to do it, as it avoids using a custom comparison function, instead using builtin comparisons. This is the ''decorate-sort-undecorate'' pattern, or the ''Schwartzian transform'' if you're coming from Perl.

{{{
#!python
sort_on = "key2"
decorated = [(dict_[sort_on], dict_) for dict_ in undecorated]
decorated.sort()
result = [dict_ for (key, dict_) in decorated]
}}}

(The variable was named {{{dict_}}} because {{{dict}}} is already a builtin.)

Starting with Py2.4 the {{{list.sort()}}} method provides a {{{key=}}} argument for doing the transform in a single step.  The new {{{sorted()}}} built-in function goes a step further and encapsulates making a new sorted list while leaving the original intact.  Also, the new {{{operator.itemgetter()}}} function helps by constructing functions for key access:

{{{
>>> from operator import itemgetter
>>> result = sorted(undecorated, key=itemgetter('key2'))
}}}

This will sort on arbitrary multiple columns of the dictionary.
{{{
#!python
def multikeysort(items, columns):
    from operator import itemgetter
    comparers = [ ((itemgetter(col[1:].strip()), -1) if col.startswith('-') else (itemgetter(col.strip()), 1)) for col in columns]
    def comparer(left, right):
        for fn, mult in comparers:
            result = cmp(fn(left), fn(right))
            if result:
                return mult * result
        else:
            return 0
    return sorted(items, cmp=comparer)
}}}
You can call it like this:
{{{
>>> result = multikeysort(undecorated, ['key1', 'key2', 'key3'])
}}}
Column names preceded by '-' are sorted in descending order:
{{{
>>> result = multikeysort(undecorated, ['-key1', '-key2', '-key3'])
}}}

== See Also ==

 * [[HowTo/Sorting]]