1390
Comment: converted to 1.6 markup
|
2300
Added code for sorting on multiple columns of arbitrary type
|
Deletions are marked like this. | Additions are marked like this. |
Line 36: | Line 36: |
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 sign(a, b): if a < b: return -1 elif a > b: return 1 else: return 0 def comparer(left, right): for fn, mult in comparers: result = sign(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']) }}} |
Sorting Lists of Dictionaries
Frequently you want to sort a list of dictionaries, based on some particular key.
For example:
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.
(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.
1 def multikeysort(items, columns):
2 from operator import itemgetter
3 comparers = [ ((itemgetter(col[1:].strip()), -1) if col.startswith('-') else (itemgetter(col.strip()), 1)) for col in columns]
4 def sign(a, b):
5 if a < b: return -1
6 elif a > b: return 1
7 else: return 0
8 def comparer(left, right):
9 for fn, mult in comparers:
10 result = sign(fn(left), fn(right))
11 if result:
12 return mult * result
13 else:
14 return 0
15 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'])