Списки и кортежи — важные структуры данных в Python. Иногда вам может понадобиться отсортировать список кортежей. В этой статье мы рассмотрим, как использовать функцию sorted()
и метод sort()
, а также разберем различия между ними. Вы узнаете, как происходит сортировка кортежей в Python, и увидите, как дополнительные параметры key
и reverse
расширяют возможности сортировки.
Инициализация списков и кортежей
Во-первых, что такое список? Начинающему пользователю легко перепутать списки с массивами. Однако списки и массивы — это принципиально разные структуры данных. Массив — это структура данных фиксированной длины, в то время как список — это структура данных переменной длины, размер которой можно изменять.
В Python списки относятся к изменяемым типам данных. Они могут содержать любые данные, включая строки, кортежи и множества. В этой статье мы будем рассматривать исключительно списки кортежей.
От редакции Pythonist: об изменяемости объектов в Python читайте в статье «Изменяемые и неизменяемые типы данных в Python».
Существует два способа инициализации пустого списка. Во-первых, вы можете указать пару квадратных скобок без каких-либо значений. Пример:
lst = []
Мы можем добавить несколько значений по умолчанию между нашими квадратными скобками. Списки Python позволяют нам иметь любое количество элементов разных типов:
jobs = ['Software Engineer','Data Analyst', 15, True]
Здесь мы объявили объект списка jobs
с четырьмя начальными значениями: 'Software Engineer'
и 'Data Analyst'
(хранятся как строки), 15
(целое число) и булево значение True
.
Еще один способ инициализировать пустой список в Python — использовать конструктор list()
. Вот пример конструктора list()
в действии:
lst = list()
Конструктор list()
принимает один необязательный аргумент — итерируемый объект (англ. iterable). Если конструктору не передан параметр, он возвращает пустой список. Если передан параметр iterable
, он возвращает список элементов iterable
.
Оба подхода дают один и тот же результат: пустой список. Каких-либо рекомендаций по выбору того или иного подхода нет. Но в силу лаконичности обычно предпочтение отдается пустым квадратным скобкам []
.
Теперь давайте разберемся, что такое кортежи в Python.
От редакции Pythonist: о том, что такое кортежи, читайте в статье «Кортежи в Python».
Кортежи, как и списки, представляют собой структуры данных с упорядоченным рядом из нуля или более записей. Основное различие между кортежами и списками заключается в том, что кортежи не могут быть изменены (они неизменяемы), а списки, как уже говорилось, изменяемы.
Для инициализации кортежа значениями используется последовательность значений, разделенных запятыми. Как и в случае со списками, есть два способа инициализации пустого кортежа. Как видите, эти методы инициализации довольно похожи:
# Метод 1 tup = () # Метод 2 tup = tuple()
Важно помнить, что если вы хотите создать кортеж с одним значением, после значения нужно поставить запятую:
# Кортеж с 1 элементом tup = (1, )
От редакции Pythonist: о различиях между списками и кортежами читайте в статье «Чем отличается кортеж от списка в Python».
Функция sorted()
Теперь давайте рассмотрим сортировку в Python.
Сортировка списка в Python может быть легко выполнена с помощью функции sorted()
. Она возвращает список с элементами, отсортированными в порядке возрастания или убывания. Синтаксис этой функции следующий:
sorted(list, key=..., reverse=...)
Обратите внимание, что key
и reverse
— два необязательных параметра:
reverse
: если этот параметр имеет значениеTrue
, то список будет сортироваться в обратном порядке (по убыванию)key
: функция, которая действует как своего рода ключ сравнения.
Метод sort()
Метод sort()
сортирует элементы списка по возрастанию (поведение по умолчанию) или по убыванию.
Синтаксис метода sort()
следующий:
list.sort(key=..., reverse=...)
По умолчанию параметр reverse
имеет значение False
. При этом метод сортирует список в порядке возрастания.
Основное различие между sort()
и sorted()
заключается в том, что sort()
сортирует список на месте, то есть изменяет сам список и возвращает значение None. Функция sorted()
создает копию исходного списка, сортирует его и возвращает этот новый список, оставляя исходный список неизменным.
Теперь давайте перейдем к сортировке списков кортежей в Python.
От редакции Pythonist: возможно, вам также будет интересна статья «Сортировка словаря по значению».
Сортировка списка кортежей с помощью функции sorted()
Чтобы понять, как сортировать кортежи в Python, давайте рассмотрим пример. Допустим, у нас есть следующий список кортежей:
sample = [(2, 4, 3), (3, 5, 7), (1, 0, 1)]
Теперь применим функцию sorted()
:
print(sorted(sample)) # Output: # [(1, 0, 1), (2, 4, 3), (3, 5, 7)]
Как видите, порядок кортежей в списке изменился.
По умолчанию метод sorted()
сортирует кортежи, ориентируясь на их первые элементы. В результате первый кортеж отсортированного списка начинается с 0, второй — с 2, а третий — с 3.
Посмотрим, что произойдет, если первые элементы всех кортежей будут одинаковыми:
sample = [(1, 4, 3), (1, 5, 7), (1, 0, 1)] print(sorted(sample)) # Output: # [(1, 0, 1), (1, 4, 3), (1, 5, 7)]
Критерием сортировки становится следующие (вторые) элементы кортежей.
Если вторые элементы всех кортежей в списке одинаковы, то сортировка кортежей будет производиться по третьему элементу. Если первый, второй и третий элементы одинаковы, то используется четвертый элемент и так далее.
Сортировка списка кортежей с помощью метода sort()
Метод sort()
также можно использовать для сортировки кортежей в Python. Начнем с исходного списка кортежей:
sample = [(2, 4, 3), (3, 5, 7), (1, 0, 1)] sample.sort() print(sample) # Output: # [(1, 0, 1), (2, 4, 3), (3, 5, 7)]
Обратите внимание, что вывод будет одинаковым независимо от того, используете ли вы sort()
или sorted()
. Однако sort()
изменяет сам объект, а sorted()
возвращает отсортированную копию списка.
Сортировка списка по второму элементу кортежа
Если вы хотите отсортировать список кортежей по заданному элементу, вы можете использовать метод sort()
и указать лямбда-функцию в качестве ключа.
К сожалению, Python не позволяет напрямую указывать индекс элемента сортировки. Вместо этого внутри параметра key должна быть определена функция, которая поможет методу sort()
выбрать нужный индекс. Функция лямбда позволяет указать в методе sort()
пользовательскую функцию-компаратор.
Например:
sample = [('Jack', 76), ('Beneth', 78), ('Cirus', 77), ('Faiz', 79)] sample.sort(key=lambda a: a[1]) print(sample)
Выполнение этого кода (который предписывает Python отсортировать список кортежей по второму элементу), даст следующий результат:
[(‘Jack’, 76), (‘Cirus’, 77), (‘Beneth’, 78), (‘Faiz’, 79)]
Сортировка списка кортежей в обратном порядке
Python позволяет указать порядок сортировки списка. Для сортировки списка кортежей по убыванию мы можем просто использовать тот же метод sort()
. Сначала мы возьмем несортированный список кортежей, а затем вызовем метод sort()
. Если передать ему в качестве аргумента reverse=True
, это изменит порядок сортировки с возрастающего на убывающий.
Давайте рассмотрим это на примере:
sample = [(1, 0, 0), (4, 1, 2), (4, 2, 5), (1, 2, 1)] sample.sort(reverse=True) print(sample) # Output: # [(4, 2, 5), (4, 1, 2), (1, 2, 1), (1, 0, 0)]
Мы также можем отсортировать список кортежей по второму элементу в обратном порядке:
sample = [('f', 90), ('g', 84), ('d', 92), ('a', 96)] sample.sort(key=lambda i:i[1], reverse=True) print(sample) # Output: # [('a', 96), ('d', 92), ('f', 90), ('g', 84)]
Использование sorted() без лямбда-функции
В предыдущем примере мы передали лямбда-функцию в качестве необязательного аргумента key метода sort()
. Но мы можем разработать обычную функцию, имитирующую встроенную функциональность лямбда-функции, и передать ее в качестве key
.
Давайте определим функцию second_item()
, которая принимает кортеж в качестве параметра и возвращает второй элемент кортежа.
def second_item(data): return data[1]
А теперь вызовем функцию sorted()
и передадим в качестве аргумента key
нашу функцию second_item
:
sample = [(1, 7, 3), (4, 9, 6), (7, 3, 9)] sample.sort(key=select_item) print(sample) # Output: # [(7, 3, 9), (1, 7, 3), (4, 9, 6)]
Результат правильный.
Сортировка списка кортежей с помощью itemgetter()
Альтернативой использованию лямбды или пользовательской функции в параметре key
является использование функции itemgetter()
из модуля operator. Прежде чем применить эту функцию, давайте рассмотрим, как она работает:
from operator import itemgetter print(itemgetter(1)((2, 5, 3))) # Output: # 5
Функция itemgetter()
возвращает элемент по переданному ей индексу (в данном случае 1). Теперь давайте воспользуемся функцией itemgetter()
для сортировки нашего списка кортежей:
sample = [(1, 7, 3), (4, 9, 6), (7, 3, 9)] print(sorted(sample, key=itemgetter(1))) # Output: # [(7, 3, 9), (1, 7, 3), (4, 9, 6)]
Здесь мы опять сортируем список кортежей по их вторым элементам.
Сортировка списка кортежей по двум элементам
До сих пор мы рассматривали сортировку кортежей по какому-нибудь одному элементу. Но для сравнения можно использовать и два, и более элементов.
Мы по-прежнему будем использовать необязательный аргумент key
, а также лямбда-функцию. Допустим, мы хотим отсортировать список по второму и третьему элементам каждого кортежа.
Мы можем использовать лямбду для возврата кортежа из двух значений, которые определяют положение элементов, используемых для сортировки, при передаче кортежа в качестве входных данных.
sample = [(2, 4, 7), (3, 0, 1), (3, 0, 0)] print(sorted(sample, key=lambda x: (x[1], x[2]))) # Output: # [(3, 0, 0), (3, 0, 1), (2, 4, 7)]
Кортежи в списке сортируются по второму элементу, а затем по третьему. Если изменить порядок элементов, заданный в лямбде, то элементы будут отсортированы по второму элементу, а затем по третьему.
Итоги
Сортировка списка кортежей может показаться сложной задачей, но в Python это легко. Язык предоставляет все необходимое для сортировки без необходимости написания собственных функций. Создавать собственную функцию придется разве что для передачи в параметре key
.
Перевод статьи «How to Sort a List of Tuples in Python».