Данные часто собираются и хранятся в беспорядке, но чтобы проанализировать их, как правило, нужно их сперва отсортировать – по возрастанию или убыванию. В этом выпуске – о том, как устроена сортировка в Python.

Видео: Глеб Лиманский

Алгоритм Bubble Sort

Есть несколько алгоритмов сортировки, рассмотрим самый простой. Bubble sort или пузырьковая сортировка получила такое название, потому что с ее помощью мы постепенно перемещаем элементы таким образом, что наименьший оказывается в самом начале, так же как пузырек воздуха всплывает в воде наверх. А самый большой элемент, наоборот, опускается вниз – то есть в конец массива.

Этот метод по очереди сравнивает каждые два соседних элемента и переставляет их местами, если порядок неправильный. Например, возьмем следующий ряд чисел: 67381. Сначала алгоритм сравнит первые два соседних числа: 6 меньше 7, значит порядок правильный, они остаются на своих местах. Затем следующие два числа – 7 больше 3, значит они меняются местами. Затем он сравнит 7 и 8, и тоже переставит их местами и так далее. После первого прохода по ряду чисел в конце окажется самое большое число – 8. И дальше алгоритм проходит по всем числам снова и будет проходить столько раз, пока каждое число не встанет на свое место – от меньшего к большему.

Вот как это выглядит на языке Питон. Есть список с числами в рандомном порядке, который нужно отсортировать. Сперва сравним первые два числа и поменяем их местами, если порядок неправильный – то есть второе число больше первого. И попросим распечатать получившийся список.

Этот код сравнил 6 с 7, и оставил их на своих местах. Теперь сравним следующие два числа: меняем в коде индексы на 1 и 2. И видим, что он сравнил 3 и 7 и поменял их местами.

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

Этот код постепенно переместил 8 в конец, после одного обхода одно число нашло свое правильное место. Но на этом сортировка не заканчивается. Нам нужно, чтобы каждый элемент массива переместился на свое место – значит нужно сделать столько обходов, сколько у нас чисел. Поэтому мы создаем новый цикл с количеством итераций, равным длине списка. Но здесь мы увидим, что на последнем обходе ничего не поменяется, потому что когда 3 нашла свое место, самый минимальный элемент 1 тоже встал на свое место, значит мы можем отнять 1, чтобы не делать последний обход. Как еще можно оптимизировать этот код? После каждого обхода в конце списка оказывается наибольшее число, и сравнение тех чисел, которые уже нашли свое место, производить не надо. Поэтому мы можем отнять внутри цикла количество обходов, соответствующее итерации цикла – run. Тогда код не будет выполнять лишних операций сравнения.

Давайте теперь превратим наш алгоритм в функцию, которой можно будет передавать любые другие массивы. И протестируем ее на новом списке.

Встроенные методы и функции сортировки

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

Метод .sort() сортирует список и сохраняет его в отсортированном виде. А функция sorted() создает новый отсортированный список без изменения исходного.

Еще одно их отличие в том, что функция sorted работает не только со списками, но и другими объектами. Например, вот что получится, если мы отсортируем строку.

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

По умолчанию сортировка будет происходить по возрастанию, но мы можем передавать функции и методу параметры. За это отвечает параметр reverse. Если мы передадим ему параметр True, сортировка будет происходить по убыванию.

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

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

Если мы хотим, чтобы сортировка происходила не по первому элементу, мы можем сами создать специальную функцию. 

С помощью функций мы можем производить сортировку и внутри словарей – например, отсортировать эти данные по доходу супруги чиновника из ФСБ.

Теперь вы умеете сортировать данные с помощью Python. Тетрадку этого урока можно скачать на нашем GitHub.