Это связано с различными другими вопросами о сортировке значений словарей, которые я читал здесь, но я не нашел ответа. Я новичок и, возможно, я просто не видел ответа, поскольку он касается моей проблемы.
У меня есть эта функция, которую я использую в качестве пользовательского фильтра Django для сортировки результатов из списка словарей. На самом деле, на основную часть этой функции был дан ответ в связанном вопросе о 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)
Этот фильтр называется в Django следующим образом:
{% for item in stats|statleaders_has_stat:"TOT_PTS_Misc"|multikeysorting:"-TOT_PTS_Misc.value,TOT_PTS_Misc.player.last_name" %}
Это означает, что в функцию передаются два словарных значения для сортировки списка словарей. Сортировка работает с ключами словаря, но не со значениями.
Как можно отсортировать и вернуть словарь, отсортировав список словарей с более чем одним значением? В приведенном выше примере сначала по значению, а затем по фамилии.
Вот пример данных:
[{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>}]
Список должен быть отсортирован следующим образом:
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
TOT_PTS_Misc - это объект, который содержит имя игрока, а также количество очков. (Надеюсь, я объясню это правильно.)
Но должны быть произвольные значения, восходящие или нисходящие. Не всегда одинаковые значения и, возможно, более двух.
Итак, я придумал это решение, но хотел знать, имеет ли оно смысл и есть ли что-то, что следует изменить.
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))