Skip to content

Instantly share code, notes, and snippets.

@rldotai
Created February 5, 2018 04:04
Show Gist options
  • Save rldotai/a5b01bcf4316bb7b6eb8cd22d6fd7e65 to your computer and use it in GitHub Desktop.
Save rldotai/a5b01bcf4316bb7b6eb8cd22d6fd7e65 to your computer and use it in GitHub Desktop.
A slightly more convenient alternative to the builtin `sorted()` which allows you to specify a key as something other than a function.
"""
A slightly more convenient alternative to the builtin `sorted()` which allows
you to specify a key as something other than a function.
For example, with a list of lists, if you wanted to sort by the last element you
could use `sort(lstseq, key=-1)` rather than `sorted(lstseq, key=lambda x: x[-1])`.
If your key *is* a function, it behaves identically to `sorted()`, because it is
really just wrapping the builtin.
Examples
--------
# sort by index
>>> sort([[1, 2], [3, 4], [0, 5]], key=[1])
[[1, 2], [3, 4], [0, 5]]
>>> sort([[1, 2], [3, 4], [0, 5]], key=1)
[[1, 2], [3, 4], [0, 5]]
# sort by key name
>>> lst = [{'x': 109, 'y': 'm'}, {'x': 101, 'y': 'm'}, {'x': 101, 'y': 'o'}]
>>> sort(lst, 'y')
[{'x': 109, 'y': 'm'}, {'x': 101, 'y': 'm'}, {'x': 101, 'y': 'o'}]
# sort by multiple criteria
[{'x': 101, 'y': 'm'}, {'x': 109, 'y': 'm'}, {'x': 101, 'y': 'o'}]
"""
import operator
def getter(index):
"""Abstract getter function for different possible indices"""
if isinstance(index, (list, tuple)):
if len(index) == 1:
index = index[0]
return lambda x: (x[index],)
elif index:
return operator.itemgetter(*index)
else:
return lambda x: ()
else:
return operator.itemgetter(index)
def sort(iterable, key=None, reverse=False):
"""Return a sorted list from an iterable using the builtin `sorted()`.
It has the same options but is more convenient because keys can be specified as
strings or indices in addition to functions.
# sort by index
>>> sort([[1, 2], [3, 4], [0, 5]], key=[1])
[[1, 2], [3, 4], [0, 5]]
>>> sort([[1, 2], [3, 4], [0, 5]], key=1)
[[1, 2], [3, 4], [0, 5]]
# sort by key name
>>> lst = [{'x': 109, 'y': 'm'}, {'x': 101, 'y': 'm'}, {'x': 101, 'y': 'o'}]
>>> sort(lst, 'y')
[{'x': 109, 'y': 'm'}, {'x': 101, 'y': 'm'}, {'x': 101, 'y': 'o'}]
# sort by multiple criteria
[{'x': 101, 'y': 'm'}, {'x': 109, 'y': 'm'}, {'x': 101, 'y': 'o'}]
"""
if key is not None and not callable(key):
key = getter(key)
return sorted(iterable, key=key, reverse=reverse)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment