Подтвердить что ты не робот

Сортировка по нескольким клавишам с использованием разных порядков

Возможный дубликат:
Как написать функции сортировки ключей Python для нисходящих значений

В Python 3 довольно легко отсортировать список объектов лексикографически, используя несколько ключей. Например:

items.sort(key = lambda obj: obj.firstname, obj.lastname)

Аргумент reverse позволяет указать, хотите ли вы восходящий или нисходящий порядок. Но что вы делаете в случае, когда хотите сортировать по нескольким клавишам, но хотите сортировать, используя порядок убывания для первого ключа, и порядок возрастания для второго?

Например, предположим, что у нас есть объект с двумя атрибутами points и name, где points - int, а name - str. Мы хотим отсортировать список этих объектов с помощью points в порядке убывания (так, чтобы сначала был объект с наибольшим числом точек), но для объектов с равным числом points мы хотим отсортировать их по name в алфавитном порядке (по возрастанию).

Как это можно достичь?

4b9b3361

Ответ 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 гарантированно стабильна, поэтому предыдущий порядок сохраняется, когда встречаются эквивалентные ключи.