Created
May 29, 2010 10:49
-
-
Save malero/418204 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Sort a list of dictionary objects by a key - case sensitive | |
from operator import itemgetter | |
mylist = sorted(mylist, key=itemgetter('name')) | |
# Sort a list of dictionary objects by a key - case insensitive | |
mylist = sorted(mylist, key=lambda k: k['name'].lower()) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Sort by multiple keys - case sensitive | |
from operator import itemgetter | |
mylist = sorted(mylist, key=itemgetter('name', 'age')) | |
# Sort by multiple keys - case insensitive | |
mylist = sorted(mylist, key=lambda k: (k['name'].lower(), k['age'])) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Sort name alphabetically and age in descending order | |
mylist = sorted(mylist, key=lambda k: (k['name'].lower(), -k['age'])) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from operator import itemgetter | |
def multikeysort(items, columns, functions={}, getter=itemgetter): | |
"""Sort a list of dictionary objects or objects by multiple keys bidirectionally. | |
Keyword Arguments: | |
items -- A list of dictionary objects or objects | |
columns -- A list of column names to sort by. Use -column to sort in descending order | |
functions -- A Dictionary of Column Name -> Functions to normalize or process each column value | |
getter -- Default "getter" if column function does not exist | |
operator.itemgetter for Dictionaries | |
operator.attrgetter for Objects | |
""" | |
comparers = [] | |
for col in columns: | |
column = col[1:] if col.startswith('-') else col | |
if not column in functions: | |
functions[column] = getter(column) | |
comparers.append((functions[column], 1 if column == col else -1)) | |
def comparer(left, right): | |
for func, polarity in comparers: | |
result = cmp(func(left), func(right)) | |
if result: | |
return polarity * result | |
else: | |
return 0 | |
return sorted(items, cmp=comparer) | |
def compose(inner_func, *outer_funcs): | |
"""Compose multiple unary functions together into a single unary function""" | |
if not outer_funcs: | |
return inner_func | |
outer_func = compose(*outer_funcs) | |
return lambda *args, **kwargs: outer_func(inner_func(*args, **kwargs)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# We will use a list of dictionary objects representing students, their classes and their current grade | |
students = [ | |
{'name':'Paul Allen', 'class':'Science','grade':'A'}, | |
{'name':'paul allen', 'class':'Math','grade':'C'}, | |
{'name':'Bob Lewis', 'class':'Science','grade':'D'}, | |
{'name':'Bob Lewis', 'class':'math','grade':'b'}, | |
{'name':'bob Lewis', 'class':'History','grade':'f'}, | |
] | |
# Sort by class and grade descending, case sensitive | |
ex1 = multikeysort(students, ['class', '-grade']) | |
# Sort by class and grade descending, case insensitive | |
from operator import itemgetter, methodcaller | |
# Create a unary function that will get the column value and then call the .lower() method | |
get_class = compose(itemgetter('class'), methodcaller('lower')) | |
get_grade = compose(itemgetter('grade'), methodcaller('lower')) | |
ex1 = multikeysort(students, ['class', '-grade'],{'class':get_class,'grade':get_grade}) |
python-3 version
from functools import cmp_to_key
from operator import itemgetter, methodcaller
def cmp(a, b):
try:
return (a > b) - (a < b)
except TypeError:
return -1
def multikeysort(items, columns, functions={}, getter=itemgetter):
"""Sort a list of dictionary objects or objects by multiple keys bidirectionally.
Keyword Arguments:
items -- A list of dictionary objects or objects
columns -- A list of column names to sort by. Use -column to sort in descending order
functions -- A Dictionary of Column Name -> Functions to normalize or process each column value
getter -- Default "getter" if column function does not exist
operator.itemgetter for Dictionaries
operator.attrgetter for Objects
"""
comparers = []
for col in columns:
column = col[1:] if col.startswith('-') else col
if not column in functions:
functions[column] = getter(column)
comparers.append((functions[column], 1 if column == col else -1))
def comparer(left, right):
for func, polarity in comparers:
result = cmp(func(left), func(right))
if result:
return polarity * result
else:
return 0
return sorted(items, key=cmp_to_key(comparer))
def compose(inner_func, *outer_funcs):
"""Compose multiple unary functions together into a single unary function"""
if not outer_funcs:
return inner_func
outer_func = compose(*outer_funcs)
return lambda *args, **kwargs: outer_func(inner_func(*args, **kwargs))
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The 4th method is really elegant and neat. Thanks a lot !!