Использование 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']