Сортировка списка кортежей в Python

Списки и кортежи — важные структуры данных в 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».