Замысловатая сортировка на питоне
Пусть есть список объектов (или словарей):
obj_lst = [
{"score": 90, "name": "рожь", "rank": 1},
{"score": 90, "name": "овес", "rank": 1},
{"score": 95, "name": "пшеница мягк 3", "rank": 1},
{"score": 95, "name": "пшеница мягк 4", "rank": 1},
{"score": 95, "name": "пшеница тв 3", "rank": 2},
{"score": 95, "name": "пшеница тв 4", "rank": 2}
]
Хочу получить отсортированный список:
{"score": 95, "name": "пшеница мягк 3", "rank": 1}
{"score": 95, "name": "пшеница мягк 4", "rank": 1}
{"score": 95, "name": "пшеница тв 3", "rank": 2}
{"score": 95, "name": "пшеница тв 4", "rank": 2}
{"score": 90, "name": "рожь", "rank": 1},
{"score": 90, "name": "овес", "rank": 1}
Применяю:
obj_lst_sorted = sorted(sorted(obj_lst , key=itemgetter("score"), reverse=True), key=itemgetter("rank"))
Получаю:
{"score": 95, "name": "пшеница мягк 3", "rank": 1}
{"score": 95, "name": "пшеница мягк 4", "rank": 1}
{"score": 90, "name": "рожь", "rank": 1}
{"score": 90, "name": "овес", "rank": 1}
{"score": 95, "name": "пшеница тв 3", "rank": 2}
{"score": 95, "name": "пшеница тв 4", "rank": 2}
Ответы (2 шт):
Автор решения: MaxU
→ Ссылка
Timsort, применяемый в sorted() - стабильный алгоритм сортировки, поэтому сначала отсортировав по ключу "name", мы сортируем результат по ключу "score" и для одинаковых "score" - результат предыдущей сортировки сохранится:
res = sorted(
sorted(obj_lst, key=itemgetter("name")),
key=itemgetter("score"),
reverse=True)
результат:
In [108]: res
Out[108]:
[{'score': 95, 'name': 'пшеница мягк 3', 'rank': 1},
{'score': 95, 'name': 'пшеница мягк 4', 'rank': 1},
{'score': 95, 'name': 'пшеница тв 3', 'rank': 2},
{'score': 95, 'name': 'пшеница тв 4', 'rank': 2},
{'score': 90, 'name': 'овес', 'rank': 1},
{'score': 90, 'name': 'рожь', 'rank': 1}]
Автор решения: CrazyElf
→ Ссылка
Для числовых полей такая сортировка легко делается с использованием кортежа в качестве ключа сортировки:
obj_lst_sorted = sorted(obj_lst, key=lambda x: (-x["score"], x["rank"]))
Сначала думал, что поля будут символьные, с ними вот сложнее, пока лёгкого метода не нашёл. А для числовых полей ответ с кортежем уже давался тут неоднократно.