This is related to the various other questions about sorting values of dictionaries that I have read here, but I have not found the answer. I'm a newbie and maybe I just didn't see the answer as it concerns my problem.
I have this function, which I'm using as a Django custom filter to sort results from a list of dictionaries. Actually, the main part of this function was answered in a related question on stackoverflow.
def multikeysorting(dict_list, sortkeys):
from operator import itemgetter
def multikeysort(items, columns):
comparers = [ ((itemgetter(col[1:]), -1) if col.startswith('-') else (itemgetter(col), 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)
keys_list = sortkeys.split(",")
return multikeysort(dict_list, keys_list)
This filter is called as follows in Django:
{% for item in stats|statleaders_has_stat:"TOT_PTS_Misc"|multikeysorting:"-TOT_PTS_Misc.value,TOT_PTS_Misc.player.last_name" %}
This means that there are two dictionary values passed to the function to sort the list of dictionaries. The sort works with the dictionary keys, but not the values.
How can I sort the and return the dictionary by sorting the list of dictionaries with more than one value? In the example above, first by the value, then by the last_name.
Here is an example of the data:
[{u'TOT_PTS_Misc': < StatisticPlayerRollup: DeWitt, Ash Total Points : 6.0>, 'player': < Player: DeWitt, Ash>}, {u'TOT_PTS_Misc': < StatisticPlayerRollup: Ackerman, Luke Total Points : 18.0>, 'player': < Player: Ackerman, Luke>}, {u'TOT_PTS_Misc': < StatisticPlayerRollup: Wise, Dan Total Points : 19.0>, 'player': < Player: Wise, Dan>}, {u'TOT_PTS_Misc': < StatisticPlayerRollup: Allison, Mike Total Points : 18.0>, 'player': < Player: Allison, Mike>}, {u'TOT_PTS_Misc': < StatisticPlayerRollup: Wolford, Alex Total Points : 18.0>, 'player': < Player: Wolford, Alex>}, {u'TOT_PTS_Misc': < StatisticPlayerRollup: Okes, Joe Total Points : 18.0>, 'player': < Player: Okes, Joe>}, {u'TOT_PTS_Misc': < StatisticPlayerRollup: Grattan, Paul Total Points : 18.0>, 'player': < Player: Grattan, Paul>}]
The listing should be sorted as follows:
LastName Points Wise 19.0 Ackerman 18.0 Allison 18.0 Grattan 18.0 Okes 18.0 Wolford 18.0 Hagg 6.0 DeWitt 6.0
The TOT_PTS_Misc is an object that contains the player name as well as the number of points. (I hope I am explaining this correct.)
But, there should be an arbitrary sort of values, either ascending or descending. Not always that same values and possibly more than two.
So I came up with this solution, but wanted to know if it makes sense and if there is anything that should be changed.
def multikeysorting(dict_list, sortkeys): from operator import itemgetter, attrgetter klist = sortkeys.split(",") vlist = [] for i in klist: vlist.append(tuple(i.split("."))) def getkeyvalue(val_list): result = [] for id,val in enumerate(val_list): if val[0].startswith('-'): if len(val) == 2: result.append((itemgetter(val[0][1:]).attrgetter(val[1]), -1)) else: att = val[1] for j in val[2:]: att = att + "." + j result.append((itemgetter(val[0][1:]).attrgetter(att), -1)) else: if len(val) == 2: result.append((itemgetter(val[0]).attrgetter(val[1]), 1)) else: att = val[1] for j in val[2:]: att = att + "." + j result.append((itemgetter(val[0]).attrgetter(att), 1)) return result return sorted(dict_list, key=getkeyvalue(vlist))