Использование key для упорядочивания данных в Python

Раздел: Алгоритмы -> Сортировка данных

Параметр key в сортировке Python

Методы sort и функция sorted в Python принимают необязательный аргумент key, который позволяет задать функцию, вычисляющую значение для сравнения элементов. Это даёт возможность сортировать данные по произвольным критериям без изменения самих элементов.

Наиболее эффективное и распространённое решение - использование анонимной функции (lambda) в качестве key. Например, сортировка списка строк по длине:

words = ['яблоко', 'груша', 'слива', 'арбуз']
words.sort(key=lambda x: len(x))
print(words)  # ['груша', 'слива', 'яблоко', 'арбуз']

Python sort key (сортировка с параметром key в python)

Функция key применяется к каждому элементу один раз и её результат используется для сравнения. Это эффективнее, чем компаратор, вызываемый многократно. Встроенные функции, такие как len, str.lower, operator.itemgetter, также часто применяются в качестве key.

Как отсортировать список чисел по модулю?

Использование lambda с функцией abs:

nums = [-7, 3, -1, 5]
sorted_nums = sorted(nums, key=lambda x: abs(x))
print(sorted_nums)  # [-1, 3, 5, -7]

сортировка по алфавиту python (сортировка по алфавиту в python)

Типичная ошибка: попытка передать строку как key (например, key='len'). Key должен быть вызываемым объектом (функцией), а не строкой. Правильно: key=len.

Как отсортировать список кортежей по второму элементу?

Использование operator.itemgetter или lambda:

pairs = [(1, 'z'), (2, 'a'), (3, 'c')]
from operator import itemgetter
pairs.sort(key=itemgetter(1))
print(pairs)  # [(2, 'a'), (3, 'c'), (1, 'z')]

Проблема: если кортежи имеют разную длину, itemgetter вызовет ошибку. Лучше использовать lambda с проверкой.

Как отсортировать список словарей по значению ключа?

Аналогично itemgetter или lambda:

users = [{'name': 'Alice', 'age': 30}, {'name': 'Bob', 'age': 25}]
sorted_users = sorted(users, key=lambda x: x['age'])
print(sorted_users)  # [{'name': 'Bob', 'age': 25}, {'name': 'Alice', 'age': 30}]

Как отсортировать объекты пользовательского класса по атрибуту?

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __repr__(self):
        return f'{self.name} ({self.age})'

people = [Person('Ann', 22), Person('Tom', 18)]
people.sort(key=lambda p: p.age)
print(people)  # [Tom (18), Ann (22)]

Как выполнить сортировку с обратным порядком, используя key?

Аргумент reverse=True работает после применения key:

data = ['apple', 'banana', 'kiwi']
data.sort(key=len, reverse=True)
print(data)  # ['banana', 'apple', 'kiwi']

Как отсортировать строки лексикографически без учёта регистра?

fruits = ['Apple', 'banana', 'Cherry']
sorted_fruits = sorted(fruits, key=str.lower)
print(sorted_fruits)  # ['Apple', 'banana', 'Cherry']

Ошибка: использование key=str не меняет регистр, поэтому заглавные буквы будут идти первыми из-за ASCII кодов. Для корректного сравнения без учёта регистра применяют str.lower или str.casefold для более широкой поддержки Unicode.

Как отсортировать по нескольким критериям (сначала по длине, потом по алфавиту)?

В lambda возвращается кортеж:

items = ['aa', 'b', 'ccc', 'a']
sorted_items = sorted(items, key=lambda x: (len(x), x))
print(sorted_items)  # ['a', 'b', 'aa', 'ccc']

Расширенные примеры использования key

Сортировка по последнему символу строки

Пример
words = ['abc', 'bca', 'cab']
result = sorted(words, key=lambda s: s[-1])
print(result)  # ['bca', 'cab', 'abc']

Сортировка чисел по сумме цифр

Пример
def sum_digits(n):
    return sum(int(d) for d in str(abs(n)))

numbers = [123, 45, 678, 9]
sorted_numbers = sorted(numbers, key=sum_digits)
print(sorted_numbers)  # [9, 45, 123, 678]

Сортировка списка дат (строк) по дате

Пример
from datetime import datetime
dates = ['2023-03-01', '2022-12-25', '2023-01-15']
sorted_dates = sorted(dates, key=lambda d: datetime.strptime(d, '%Y-%m-%d'))
print(sorted_dates)  # ['2022-12-25', '2023-01-15', '2023-03-01']

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

Пример
matrix = [[3, 1, 2], [1, 3, 2], [2, 2, 1]]
# сортировка по первому элементу, потом по третьему
result = sorted(matrix, key=lambda row: (row[0], row[2]))
print(result)  # [[1, 3, 2], [2, 2, 1], [3, 1, 2]]

Сортировка с использованием functools.cmp_to_key (для старых компараторов)

Пример
from functools import cmp_to_key
def compare(a, b):
    if a < b: return -1
    elif a > b: return 1
    else: return 0

nums = [3, 1, 4, 1, 5]
nums.sort(key=cmp_to_key(compare))
print(nums)  # [1, 1, 3, 4, 5]

Сортировка по атрибуту с помощью attrgetter

Пример
from operator import attrgetter
class User:
    def __init__(self, name, rank):
        self.name = name
        self.rank = rank
users = [User('John', 10), User('Jane', 5), User('Jack', 7)]
users.sort(key=attrgetter('rank'))
print([u.name for u in users])  # ['Jane', 'Jack', 'John']

Сортировка с пользовательским ключом, возвращающим кортеж из условия

Пример
items = ['cat', 'dog', 'mouse', 'bird']
# сначала все, что содержат 'o', потом по алфавиту
result = sorted(items, key=lambda x: (0 if 'o' in x else 1, x))
print(result)  # ['dog', 'mouse', 'bird', 'cat']

Результат работы кода:

['dog', 'mouse', 'bird', 'cat']

Сортировка с параметром key в Python - comments

En
Python sort key (python)