Сортировка в Python

Как работает то, чем мало кто пользуется (а зря)

Сортировка в Python

В языке Python есть полезные и удобные структуры элементов, которые называются «коллекции». К ним относятся списки, кортежи, строки, словари.

Для работы с коллекциями есть много инструментов, и мы уже разобрали многие:

Сегодня продолжим и научимся работать с сортировкой элементов через функцию sorted() и метод sort().

Функции сортировки в Python

В Питоне есть много методов, чтобы привести элементы составного массива в порядок. Большинство требуют дополнительной установки через внешние библиотеки, но есть два встроенных, которыми можно быстро отсортировать разные типы данных, — их сегодня и разберём.

Функция sorted()

Работает с любым итерируемым объектом в Python. Итерируемым считается любой объект, элементы которого можно перебирать циклом for. Например, так мы проходим по элементам строки и выводим на экран каждый символ, который перебирает цикл:

# перебираем каждый символ строки Hello
for letter in "Hello":
   # каждый проверяемый символ выводим на экран
   print(letter)

Результатом будут буквы, выведенные по отдельности:

H
e
l
l
o

Строка Hello — итерируемый объект, к которому можно применить функцию sorted(). Как именно это делать, что можно получить и какие другие виды объектов сортировать, рассмотрим дальше.

sorted() не изменяет тот объект, который мы ей отдаём, а создаёт новый список из отсортированных элементов, независимо от того, какой объект мы дадим для работы. Это добавляет надёжности, потому что разработчик не может случайно изменить этим инструментом что-то в исходных данных.

Метод sort()

Может итерировать и сортировать не любую коллекцию, а только списки.

У этого подхода есть свои плюсы и минусы по сравнению с функцией sorted(). Одно из главных различий — sort() изменяет исходный список вместо создания нового. Это делает код сложнее в использовании, потому что нужно учитывать и помнить об изменениях в первоначальном объекте.

Синтаксис и параметры

Чтобы использовать функцию sorted() или метод sort(), нужно передать итерируемую коллекцию и при необходимости указать правило сортировки и дополнительную метку-флаг: по возрастанию или убыванию применять сортировку.

Если передать только итерируемый объект, то по умолчанию выполняется сортировка по возрастанию. Для чисел это будет возрастание от меньшего числа к большему, а для строк — по соответствию символов в таблице ASCII, которая состоит из 127 пронумерованных элементов и используется для вывода символов на экран. Чем выше элемент стоит в таблице — тем ближе к началу списка его поместит сортировка по умолчанию.

Буквы русского алфавита тоже можно использовать, тогда Python будет использовать номера символов в таблице Unicode.

Если сортировать коллекцию по значениям True и False, то сначала будет идти False.

Синтаксис функции sorted()

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

sorted()

Если сортировку нужно выполнить по каким-то своим правилам, в скобках прописываются все нужные аргументы:

sorted(iterable, key=None, reverse=False)

Параметры функции sorted()

Что есть что в команде выше:

  • sorted() — ключевое слово для вызова встроенной функции. Для использования не нужно отдельно импортировать модули, можно сразу писать команду.
  • iterable — итерируемый объект, элементы которого нужно отсортировать.
  • key — параметр, который по умолчанию равен None. Это функция, которой можно задать сложное правило сортировки.

reverse говорит функции, как сортировать объект. Если ничего не указывать, элементы выстраиваются по возрастанию, а если нужно по убыванию, то указывается reverse=True.

Синтаксис метода sort()

Метод вызывается проще, чем функция, — после имени переменной, которая хранит список, нужно поставить точку и написать ключевое слово sort():

list.sort()

Если нужно, можно настроить все те же параметры, которые есть в функции sorted():

list.sort(key=None, reverse=False)

Итерируемый объект мы здесь не передаём, потому что метод уже вызывается у списка.

Параметры метода sort()

Параметры полностью повторяют возможные настройки функции — sort() работает точно так же, только не тратит время на создание нового объекта, а изменяет исходный список.

Способы сортировки

У встроенных методов сортировки всего два параметра, но зато один из них — функция. Это даёт возможность передать практически любое правило для сортировки.

Разберём основные варианты использования на примерах.

Сортировка по возрастанию

Чтобы было понятно, разберём примеры с числами и строками отдельно.

Сначала сортируем числа:

# создаём список чисел в разном порядке
numbers = [5, 2, 9, 1]

# сортируем числа от меньшего к большему
ascending = sorted(numbers)

# выводим результат
print(ascending)

Простая сортировка по возрастанию включена по умолчанию, поэтому дополнительно ничего указывать не надо. Запускаем код:

[1, 2, 5, 9]

Напишем такую же программу, но для строки:

# создаём список русских слов
words = ["Никулин", "Вицин", "Моргунов"]

# сортируем список по возрастанию (по алфавиту)
sorted_words = sorted(words)

# выводим результат
print(sorted_words)

Проверяем:

['Вицин', 'Моргунов', 'Никулин']

Но если мы поменяем начальную букву у 'Вицин' с прописной на строчную — 'вицин' — элемент передвинется в конец списка. Строчные буквы стоят после заглавных:

['Моргунов', 'Никулин', 'вицин']

Сортировка по убыванию

Для убывания понадобится дополнительный параметр reverse=True. Посмотрим, как будут выглядеть результаты запуска программы на предыдущем списке с числовыми элементами:

# создаём список чисел в разном порядке
numbers = [5, 2, 9, 1]

# сортируем числа от меньшего к большему
sorted_numbers = sorted(numbers, reverse=True)

# выводим результат
print(sorted_numbers)

Результат в терминале:

[9, 5, 2, 1]

Теперь инвертируем список со строками:

# создаём список русских слов
words = ["Никулин", "Вицин", "Моргунов"]

# сортируем список по возрастанию (по алфавиту)
sorted_words = sorted(words, reverse=True)

# выводим результат
print(sorted_words)

Что получилось:

['Никулин', 'Моргунов', 'Вицин']

Сортировка с использованием параметра key

В качестве параметра key можно указать любую функцию. Можно использовать что-то из готовых или написать свою.

Пример — если указать в качестве аргумента другую встроенную функцию len, программа отсортирует элементы по длине от самого короткого к самому длинному:

# создаём список строк
cities = ["Москва", "Сочи", "Владивосток", "Казань"]

# сортируем по длине названия (от короткого к длинному)
sorted_cities = sorted(cities, key=len)

# выводим результат
print(sorted_cities)

Проверяем код:

['Сочи', 'Москва', 'Казань', 'Владивосток']

Теперь сделаем посложнее. Напишем простую лямбда-функцию, которая будет возвращать последний символ строки, и отсортируем слова по последней букве:

# создаём список строк
words = ["карандаш", "линейка", "ручка", "ластик", "тетрадь"]

# сортируем список по последней букве каждого слова
# используем лямбда-функцию, которая возвращает последний символ строки
function = sorted(words, key=lambda word: word[-1])

# выводим результат
print(function)

Сначала посмотрим, что выдаёт код:

['линейка', 'ручка', 'ластик', 'карандаш', 'тетрадь']

На результате остановимся подробнее. В примере есть два элемента с одинаковой буквой на конце строки — 'линейка' и  'ручка'. Если элементы равны по первому критерию, то sorted() сохраняет исходный порядок элементов. Если поменять их местами в исходном списке:

words = ["карандаш", "ручка", "линейка", "ластик", "тетрадь"]

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

['ручка', 'линейка', 'ластик', 'карандаш', 'тетрадь']

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

В функцию можно передавать любой итерируемый объект, но результатом всегда будет список. Попробуем отсортировать кортеж:

# создаём кортеж с элементами
t = (5, 2, 9, 1, 7)

# сортируем кортеж и получаем новый список с отсортированными элементами
sorted_list = sorted(t)

# выводим результат
print(sorted_list)

По результату в консоли можно заметить, что мы получаем список — он заключён в квадратные скобки:

[1, 2, 5, 7, 9]

Попробуем создать словарь и применить sorted() без дополнительных параметров:

# создаём словарь
d = {"Аргентина": 5, "Ямайка": 0, "Мальдивы": -10}

# сортируем словарь — по умолчанию сортируются только ключи
sorted_keys = sorted(d)

# выводим результат
print(sorted_keys)

Если запустить этот код, функция создаст список только из ключей:

['Аргентина', 'Мальдивы', 'Ямайка']

Чтобы достать именно пары ключей и значений, нам понадобится метод словарей .items, который возвращает пары в виде кортежей. Отсортируем получившийся список по возрастанию значений:

# создаём словарь
d = {"Аргентина": 5, "Ямайка": 0, "Мальдивы": -10}

# сортируем товары по цене
elements = sorted(d.items(), key=lambda x: x[1])

# выводим результат
print(elements)

Запускаем код и получаем список кортежей по возрастанию второго элемента:

[('Мальдивы', -10), ('Ямайка', 0), ('Аргентина', 5)]

Различия между sorted() и sort()

Когда какой метод применять, зависит от задачи.

При работе с sorted() Python не изменяет исходный объект, поэтому этот способ безопаснее. Но если вы уверены в правильности работы кода и вам важна скорость, можно использовать sort().

sort() получится использовать только при работе со списками. Если работаете с кортежами, словарями, множествами и любыми другими коллекциями, сортировать их нужно при помощи sorted().

Метод sort() более читаемый, потому что вы сразу можете увидеть, у какого списка он вызывается. Но это скорее дополнительный критерий — а главными являются безопасность и логика работы программы.

Если точно понимаете, как безопасно встраивать работу sort() в основную логику, используйте его. Если не уверены, лучше брать sorted().

Сложная сортировка

И функция sorted(), и метод sort() умеют сортировать только однотипные элементы. Если попробовать передать им коллекцию данных разного типа, получим ошибку.

Смотрим пример:

# создаём список чисел в разном порядке
numbers_and_othes = [5, 2, 9, 1, True, False, 'Hello World']

# сортируем числа от меньшего к большему
sorted_elements = sorted(numbers_and_othes)

# выводим результат
print(sorted_elements)

Запускаем и видим в консоли сообщение, что такое не поддерживается:

TypeError: '<' not supported between instances of 'str' and 'int'

Многоуровневая сортировка

Если каждый элемент коллекции для сортировки состоит из собственных элементов, сортировку можно сделать по нескольким параметрам. Для примера возьмём такой список сотрудников, который состоит из кортежей:

[("Иван", "IT", 100), ("Аня", "HR", 90), ("Пётр", "IT", 80)]

Каждый кортеж состоит из трёх элементов: имя, отдел и зарплата. Чтобы в сортировке участвовало два параметра, мы создадим лямбда-функцию, которая сначала расставит элементы по отделу, а потом по возрастающей зарплате.

Код выглядит так:

# создаём список сотрудников: имя, отдел, зарплата
employees = [("Иван", "IT", 100), ("Аня", "HR", 90), ("Пётр", "IT", 80)]

# сортируем: 1) по отделу, 2) по зарплате (по убыванию)
order = sorted(employees, key=lambda x: (x[1], x[2]))

# выводим результат на экран
print(order)

Проверяем:

[('Аня', 'HR', 90), ('Пётр', 'IT', 80), ('Иван', 'IT', 100)]

Стабильность сортировки

Если мы попросим sorted() и sort() отсортировать коллекцию по какому-то признаку и он окажется одинаковым у нескольких элементов, алгоритм Python сохранит порядок первоначальной коллекции. 

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

Вам слово

Приходите к нам в соцсети поделиться своим мнением о статье и почитать, что пишут другие. А ещё там выходит дополнительный контент, которого нет на сайте — шпаргалки, опросы и разная дурка. В общем, вот тележка, вот ВК — велком!

Обложка:

Алексей Сухов

Корректор:

Александр Зубов

Вёрстка:

Егор Степанов

Соцсети:

Юлия Зубарева

Вам может быть интересно
easy
[anycomment]
Exit mobile version