Аргумент key для сортировки коллекций по ключу

Курс по Python: https://stepik.org/course/100707

На этом занятии мы увидим, как можно управлять алгоритмом сортировки с помощью специального параметра key, который имеется у метода sort() и функции sorted().

По умолчанию сортировка коллекции выполняется по значениям ее элементов. Например:

a = [4, 3, -10, 1, 7, 12]
b = sorted(a)
print(b)

Но мы можем вместо этих значений указать другие, которые будут использованы для сортировки элементов. Например, вычислить показатель четности значений. Тогда последовательность будет выстроена по возрастанию этих ключей. В результате увидим сначала четные значения, а потом – нечетные.

Чтобы выполнить такую манипуляцию в функции sorted() прописывается аргумент key и ему присваивается ссылка на функцию, которая будет формировать альтернативное значение элемента, то есть, ключ:

b = sorted(a, key=is_odd)

А саму функцию можно определить, следующим образом:

def is_odd(x):
    return x % 2

Здесь аргумент x – это текущее значение элемента коллекции, а то, что она возвращает, становится значением соответствующего ключа. То есть, для четных значений будем иметь 0, а для нечетных – 1. После запуска программы видим искомый результат сортировки.

Конечно, для простых функций, обычно, в аргументе key записывают лямбда-функцию. В нашем примере она будет выглядеть, следующим образом:

b = sorted(a, key=lambda x: x % 2)

Как видите, все достаточно просто.

Тот же самый аргумент key можно указывать и в методе sort() для списка:

a.sort(key=lambda x: x % 2)

Он здесь работает абсолютно также, как и в функции sorted().

Давайте теперь немного усложним нашу задачу и сделаем не просто разделение на четные и нечетные, а еще и отсортируем каждую группу по возрастанию. Для этого значения ключей я буду увеличивать на значения элементов и, кроме того, нечетным величинам изначально присваивать число 100, чтобы гарантированно разделить четные и нечетные значения именно в нашей коллекции. Это исключительно учебный пример, показывающий возможности сортировки коллекций по ключу.

Итак, для формирования таких ключей, определим следующую функцию:

def key_sort(x):
    return x if x % 2 == 0 else 100 + x

И укажем ее в функции sorted():

b = sorted(a, key=key_sort)
print(b)

Теперь у нас выполняется не только разделение на четные и нечетные значения, но и их сортировка внутри групп.

Я, думаю, что вы в целом поняли, как использовать аргумент key для управления сортировкой. И здесь, как всегда, извечный вопрос – зачем это надо? Давайте я приведу несколько более практичных примеров. Предположим, что у нас имеется список городов:

lst = ["Москва", "Тверь", "Смоленск", "Псков", "Рязань"]

И требуется их выстроить по длине. Для этого воспользуемся функцией sorted() и в аргументе key укажем стандартную функцию len:

print( sorted(lst, key=len) )

получим следующий результат:

['Тверь', 'Псков', 'Москва', 'Рязань', 'Смоленск']

Или можно сделать сортировку по последнему символу слова:

print( sorted(lst, key=lambda x: x[-1]) )

['Москва', 'Псков', 'Смоленск', 'Тверь', 'Рязань']

Или только по первому:

print( sorted(lst, key=lambda x: x[0]) )

['Москва', 'Псков', 'Рязань', 'Смоленск', 'Тверь']

И так далее.

Аргумент key часто используют для сортировки сложных структур данных. Допустим, у нас имеется вот такой кортеж, содержащий вложенные кортежи с информацией по книгам:

books = (
    ("Евгений Онегин", "Пушкин А.С.", 200),
    ("Муму", "Тургенев И.С.", 250),
    ("Мастер и Маргарита", "Булгаков М.А.", 500),
    ("Мертвые души", "Гоголь Н.В.", 190)
)

И нам нужно его отсортировать по цене (последнее значение). Очевидно, это можно сделать так:

print( sorted(books, key=lambda x: x[2]) )

На выходе получим отсортированный список:

[('Мертвые души', 'Гоголь Н.В.', 190), ('Евгений Онегин', 'Пушкин А.С.', 200), ('Муму', 'Тургенев И.С.', 250), ('Мастер и Маргарита', 'Булгаков М.А.', 500)]

Вот так используется аргумент key для управления сортировкой элементов произвольных коллекций данных. И теперь вы знаете, как его применять в своих программах.

Курс по Python: https://stepik.org/course/100707

Видео по теме