Сортировка по нескольким клавишам с использованием разных порядков
Возможный дубликат:
Как написать функции сортировки ключей Python для нисходящих значений
В Python 3 довольно легко отсортировать список объектов лексикографически, используя несколько ключей. Например:
items.sort(key = lambda obj: obj.firstname, obj.lastname)
Аргумент reverse
позволяет указать, хотите ли вы восходящий или нисходящий порядок. Но что вы делаете в случае, когда хотите сортировать по нескольким клавишам, но хотите сортировать, используя порядок убывания для первого ключа, и порядок возрастания для второго?
Например, предположим, что у нас есть объект с двумя атрибутами points
и name
, где points
- int
, а name
- str
. Мы хотим отсортировать список этих объектов с помощью points
в порядке убывания (так, чтобы сначала был объект с наибольшим числом точек), но для объектов с равным числом points
мы хотим отсортировать их по name
в алфавитном порядке (по возрастанию).
Как это можно достичь?
Ответы
Ответ 1
Нет никакого встроенного способа справиться с этим. В общем случае вы должны сортировать дважды: сначала по второму типу, затем по первичной сортировке. Как отметил в своем комментарии @Mark Ransom, во многих случаях переменные являются числовыми, поэтому вы можете использовать отрицательное значение для перевода заказа.
Если вам известен тип переменной, которую вы пытаетесь сортировать и как работать с ней, вы также можете написать ключевую функцию, которая возвращает уменьшающееся значение для увеличения ключей. См. этот поток для примера для строк. (В основном, вы берете отрицательное число ASCII числовых символов).
В Python 2 вы также можете использовать функцию cmp
вместо ключа, но это, скорее всего, сделает сортировку медленнее. Будет ли это слишком медленным, зависит от того, насколько большой и несортированный список. В Python 3 аргумент cmp
отсутствует, но как примечания @Mark Ransom вы можете использовать cmp_to_key
.
Ответ 2
items.sort(key = lambda obj: (obj.firstname, [(-ord(c) for c in obj.lastname)]))
Ответ 3
Существует functools.cmp_to_key
, чтобы преобразовать функцию сравнения в ключ, совместимый с функциями сортировки. Это было предоставлено для сортировок, которые использовали функцию сравнения в Python 2 и должны были быть преобразованы в Python 3, который больше не позволяет их.
Изменить: там также предлагается в вики Python под заголовком "Стабильность сортировки" и "Сложные сортировки" , чтобы выполнить сортировку в несколько проходов, от наименьшего существенный ключ к наиболее значимым. Это работает, потому что сортировка Python гарантированно стабильна, поэтому предыдущий порядок сохраняется, когда встречаются эквивалентные ключи.