Как проверить в питоне то что объект отсортирован
Всё о сортировке в Python: исчерпывающий гайд
Авторизуйтесь
Всё о сортировке в Python: исчерпывающий гайд
Примечание Вы читаете улучшенную версию некогда выпущенной нами статьи.
Основы сортировки
Прим.перев. В Python вернуть None и не вернуть ничего — одно и то же.
Ещё одно отличие заключается в том, что метод list.sort() определён только для списков, в то время как sorted() работает со всеми итерируемыми объектами:
Прим.перев. При итерировании по словарю Python возвращает его ключи. Если вам нужны их значения или пары «ключ-значение», используйте методы dict.values() и dict.items() соответственно.
Рассмотрим основные функции сортировки Python.
Функции-ключи
С версии Python 2.4 у list.sort() и sorted() появился параметр key для указания функции, которая будет вызываться на каждом элементе до сравнения. Вот регистронезависимое сравнение строк:
Значение key должно быть функцией, принимающей один аргумент и возвращающей ключ для сортировки. Работает быстро, потому что функция-ключ вызывается один раз для каждого элемента.
Часто можно встретить код, где сложный объект сортируется по одному из его индексов. Например:
Тот же метод работает для объектов с именованными атрибутами:
Функции модуля operator
Функции operator дают возможность использовать множественные уровни сортировки в Python. Отсортируем учеников сначала по оценке, а затем по возрасту:
Используем функцию methodcaller() для сортировки учеников по взвешенной оценке:
Сортировка по возрастанию и сортировка по убыванию в Python
Стабильность сортировки и сложные сортировки в Python
Начиная с версии Python 2.2, сортировки гарантированно стабильны: если у нескольких записей есть одинаковые ключи, их порядок останется прежним. Пример:
Обратите внимание, что две записи с ‘blue’ сохранили начальный порядок. Это свойство позволяет составлять сложные сортировки путём постепенных сортировок. Далее мы сортируем данные учеников сначала по возрасту в порядке возрастания, а затем по оценкам в убывающем порядке, чтобы получить данные, отсортированные в первую очередь по оценке и во вторую — по возрасту:
Алгоритмы сортировки Python вроде Timsort проводят множественные сортировки так эффективно, потому что может извлечь пользу из любого порядка, уже присутствующего в наборе данных.
Декорируем-сортируем-раздекорируем
Вот так можно отсортировать данные учеников по оценке:
Это работает из-за того, что кортежи сравниваются лексикографически, сравниваются первые элементы, а если они совпадают, то сравниваются вторые и так далее.
Не всегда обязательно включать индекс в декорируемый список, но у него есть преимущества:
Ещё эта идиома называется преобразованием Шварца в честь Рэндела Шварца, который популяризировал её среди Perl-программистов.
Для больших списков и версий Python ниже 2.4, «декорируем-сортируем-раздекорируем» будет оптимальным способом сортировки. Для версий 2.4+ ту же функциональность предоставляют функции-ключи.
Использование параметра cmp
Все версии Python 2.x поддерживали параметр cmp для обработки пользовательских функций сравнения. В Python 3.0 от этого параметра полностью избавились. В Python 2.x в sort() можно было передать функцию, которая использовалась бы для сравнения элементов. Она должна принимать два аргумента и возвращать отрицательное значение для случая «меньше чем», положительное — для «больше чем» и ноль, если они равны:
Можно сравнивать в обратном порядке:
При портировании кода с версии 2.x на 3.x может возникнуть ситуация, когда нужно преобразовать пользовательскую функцию для сравнения в функцию-ключ. Следующая обёртка упрощает эту задачу:
Чтобы произвести преобразование, оберните старую функцию:
В Python 2.7 функция cmp_to_key() была добавлена в модуль functools.
Поддержание порядка сортировки
Прочее
Для сортировки с учётом языка используйте locale.strxfrm() в качестве ключевой функции или locale.strcoll() в качестве функции сравнения. Параметр reverse всё ещё сохраняет стабильность сортировки. Этот эффект можно сымитировать без параметра, использовав встроенную функцию reversed() дважды:
Чтобы создать стандартный порядок сортировки для класса, просто добавьте реализацию соответствующих методов сравнения:
Pythonic способ проверить, отсортирован ли список или нет
Есть ли питонный способ проверить, отсортирован ли список уже в ASC или DESC
Я хочу ввести список временных меток для некоторых сообщений и проверить, отображаются ли транзакции в правильном порядке.
22 ответа
На самом деле мы не даем ответ, который ищет аниджхау. Вот один лайнер:
Самый простой способ:
Переменная аккумулятора просто хранит это последнее проверенное значение, и, если какое-либо значение меньше предыдущего значения, аккумулятор устанавливается на бесконечность (и, таким образом, все равно будет бесконечностью в конце, поскольку «предыдущее значение» всегда будет больше, чем текущий).
В Python 3 zip уже возвращает генератор, в Python 2 вы можете использовать itertools.izip для повышения эффективности памяти.
Бонус: проверка конечных (!) Генераторов, которые не могут быть проиндексированы:
Убедитесь, что вы используете itertools.izip здесь, если вы используете Python 2, иначе вы бы потерпели поражение от необходимости создавать списки из генераторов.
Я бы просто использовал
Если это не очень большой список, в этом случае вы можете захотеть создать пользовательскую функцию.
Если вы просто собираетесь отсортировать его, если он не отсортирован, тогда забудьте о проверке и сортируйте его.
И не думай об этом слишком много.
Если вы хотите пользовательскую функцию, вы можете сделать что-то вроде
Это будет O (n), если список уже отсортирован (и O (n) в цикле for при этом!), Поэтому, если вы не ожидаете, что он не будет отсортирован (и довольно случайен), большая часть время, я бы, опять же, просто отсортировать список.
Итак, вы можете сделать что-то вроде:
Определенно работает в Python 3 и выше для целых чисел или строк:
Другой способ узнать, отсортирован ли данный список или нет
Если вы хотите самый быстрый способ для массивов с пустым фрагментом, используйте numba, который, если вы используете conda, уже должен быть установлен
Код будет быстрым, потому что он будет скомпилирован numba
На самом деле это самый короткий способ сделать это с помощью рекурсии:
Если отсортировано, будет напечатано True, иначе будет напечатано False
Решение с использованием выражений присваивания (добавлено в Python 3.8):
Ленивый
Я использую этот однострочник на основе numpy.diff ():
Однако вы должны быть осторожны, если x является беззнаковым целым, что может привести к потере целочисленного значения в numpy.diff (), что приведет к ложному положительному результату. Вот модифицированная версия:
Эта форма итератора на 10-15% быстрее, чем при использовании целочисленной индексации:
Как отмечает @aaronsterling, следующее решение является самым коротким и кажется самым быстрым, когда массив отсортирован и не слишком мал: def is_sorted (lst): return (sorted (lst) == lst)
Если большую часть времени массив не сортируется, было бы желательно использовать решение, которое не сканирует весь массив и возвращает False, как только обнаруживается несортированный префикс. Вот самое быстрое решение, которое я смог найти, оно не особенно элегантно:
Используя эталонный тест Натана Фаррингтона, это обеспечивает лучшее время выполнения, чем использование sorted (lst) во всех случаях, кроме случаев работы с большим отсортированным списком.
Вот результаты тестов на моем компьютере.
отсортировано (lst) == первое решение
Второе решение:
Эта реализация быстра и работает на любых итерациях.
Я бы сделал это (крадя здесь множество ответов [Аарон Стерлинг, Вай Ип Тунг, Сорта из Пола МакГир) и в основном Армин Ронахер):
Одна приятная вещь: вам не нужно реализовывать вторую итерацию для серии (в отличие от фрагмента списка).
Просто чтобы добавить другой способ (даже если для этого требуется дополнительный модуль): iteration_utilities.all_monotone :
Чтобы проверить заказ DESC:
Pythonic способ проверить, отсортирован ли список или нет
есть ли способ pythonic проверить, если список уже отсортирован в ASC или DESC
Я хочу ввести список временных меток для некоторых сообщений и проверить, появились ли транзакции в правильном порядке.
19 ответов
На самом деле мы не даем ответ, который ищет аниджхав. Вот один лайнер:
Я бы просто использовать
если это не очень большой список в этом случае вы можете создать пользовательскую функцию.
если вы просто собираетесь сортировать его, если он не отсортирован, то забудьте чек и сортировать его.
и не думай об этом слишком много.
если вы хотите пользовательскую функцию, вы можете сделать что-то вроде
это будет o(n), если список уже отсортирован, хотя (и O(N) в for цикл это!) Итак, если вы не ожидаете, что он не будет отсортирован (и довольно случайный) большую часть времени, я бы снова просто отсортировал список.
эта форма итератора на 10-15% быстрее, чем при использовании целочисленной индексации:
красивый способ реализовать это-использовать
Я бы сделал это (кража из многих ответов здесь [Аарон Стерлинг, Wai Yip Tung, sorta от пола Макгира] и в основном Армин Ронахер):
одна хорошая вещь: вам не нужно реализовывать вторую итерацию для серии (в отличие от среза списка).
я запустил тест и sorted(lst, reverse=True) == lst был самым быстрым для длинных списков, и all(l[i] >= l[i+1] for i in xrange(len(l)-1)) стал самым быстрым для коротких списков. Эти тесты были запущены на MacBook Pro 2010 13″ (Core2 Duo 2.66 GHz, 4GB 1067MHz DDR3 RAM, Mac OS X 10.6.5).
обновление: я пересмотрел сценарий, чтобы вы могли запускать его непосредственно в своей собственной системе. В предыдущей версии были ошибки. Кроме того, я добавил Как отсортированные, так и несортированные входные данные.
таким образом, в большинстве случаев есть явный победитель.
обновление: ответы ааронстерлинга (#6 и #7) на самом деле самые быстрые во всех случаях. #7 является самым быстрым, потому что у него нет слоя косвенности для поиска ключа.
так что вы могли бы сделать что-то вроде:
не очень подходящие для Python, но нам нужен хотя бы один reduce() ответ, да?
переменная аккумулятора просто сохраняет это последнее проверенное значение, и если какое-либо значение меньше предыдущего значения, аккумулятор устанавливается на бесконечность (и, таким образом, все равно будет бесконечностью в конце, так как «Предыдущее значение» всегда будет больше текущего).
Я использую этот однострочный лайнер на основе numpy.diff ():
Я действительно не синхронизировал его с любым другим методом, но я предполагаю, что это быстрее, чем любой чистый метод Python, особенно для большого n, так как цикл в numpy.diff (вероятно) выполняется непосредственно в C (N-1 вычитаний с последующим N-1 сравнений).
однако вам нужно быть осторожным, если x является unsigned int, что может вызвать тихий целочисленный underflow в numpy.diff (), что приводит к ложному положительному результату. Вот измененная версия:
В Python 3, zip уже возвращает генератор, в Python 2 Вы можете использовать itertools.izip для повышения эффективности памяти.
последний терпит неудачу, когда кортеж (3, 2) is оцененный.
бонус: проверка конечного (!) генераторы, которые не могут быть проиндексированы:
обязательно используйте itertools.izip здесь, Если вы используете Python 2, иначе вы победите цель не создавать списки из генераторов.
Как отметил @aaronsterling следующее решение является самым коротким и кажется самым быстрым, когда массив отсортирован и не слишком мал: def is_sorted(lst): return(sorted (lst) == lst)
если большую часть времени массив не сортируется, было бы желательно использовать решение, которое не сканирует весь массив и возвращает False, как только обнаружен несортированный префикс. Следующее-Самое быстрое решение, которое я мог найти, это не особенно элегантный:
используя бенчмарк Натана Фаррингтона, это обеспечивает лучшее время выполнения, чем использование sorted (lst) во всех случаях, за исключением запуска в большом отсортированном списке.
вот результаты тестов на моем компьютере.
сортировка (lst)==LST решение
второй вариант:
Если вы хотите самый быстрый способ для массивов numpy, используйте numba, который, если вы используете conda, должен быть уже установлен
код будет быстрым, потому что он будет скомпилирован numba
Метод List sort() в Python
Метод List sort() в Python сортирует элементы списка в порядке возрастания.
В Python есть встроенная функция sorted(), которая используется для создания отсортированного списка из итерируемого объекта.
1. Использование метода List sort() по умолчанию
По умолчанию метод list sort() в Python упорядочивает элементы списка в порядке возрастания. Это также естественный способ сортировки элементов.
Элементы также могут быть символами или числами, и метод sort() продолжит сортировку в порядке возрастания.
2. Обратная сортировка списка
Если вы хотите, чтобы сортировка выполнялась в обратном порядке, передайте обратный аргумент, как True. Мы можем использовать это для сортировки списка чисел в порядке убывания.
3. Сортировка вложенного списка
Если мы вызываем функцию списка sort() для вложенного списка, для сортировки используются только первые элементы из элементов списка. Давайте разберемся в этом примере.
Понятно, что сортировка производится по первому элементу вложенного списка. Но иногда нам нужно отсортировать вложенный список по позициям разных элементов.
Допустим, вложенный список содержит информацию об имени, возрасте и поле человека. Давайте посмотрим, как отсортировать этот вложенный список по возрасту, который является вторым элементом вложенного списка.
Мы используем ключевой аргумент, чтобы указать элемент, который будет использоваться для целей сортировки. Функция custom_key возвращает ключ для сортировки списка.
4. Пользовательская логика для сортировки списка
Мы также можем реализовать вашу собственную логику для сортировки элементов списка.
В последнем примере мы использовали возраст как ключевой элемент для сортировки нашего списка.
Но есть такая поговорка: «Сначала дамы!». Итак, мы хотим отсортировать наш список таким образом, чтобы женский пол имел приоритет над мужским. Если пол двух человек совпадает, младший получает более высокий приоритет.
Итак, мы должны использовать ключевой аргумент в нашей функции сортировки. Но функцию сравнения нужно преобразовать в ключ.
Итак, нам нужно импортировать библиотеку под названием functools. Мы будем использовать функцию cmp_to_key(), чтобы преобразовать compare_function в key.
Список сначала сортируется по полу. Затем он сортируется по возрасту людей.
5. Сортировка списка объектов
Сортировка по умолчанию работает с числами и строками. Но это не будет работать со списком настраиваемых объектов. Посмотрим, что произойдет, когда мы попытаемся запустить сортировку по умолчанию для списка объектов.
В этом случае мы должны в обязательном порядке предоставить ключевую функцию для указания поля объектов, которое будет использоваться для сортировки.
Мы также можем использовать модуль functools для создания пользовательской логики сортировки для элементов списка.
Алгоритмы сортировки на Python
В этой статье мы вкратце расскажем, какие есть основные алгоритмы сортировки и каковы их главные характеристики. Также по каждому алгоритму покажем реализацию на Python.
Искусство наведения порядка
Сортировка означает размещение элементов в определенном порядке. Этот конкретный порядок определяется свойством сравнения элементов. В случае целых чисел мы говорим, что сначала идет меньшее число, а потом — большее.
Расположение элементов в определенном порядке улучшает поиск элемента. Следовательно, сортировка широко используется в информатике.
В данной статье мы рассмотрим обычные алгоритмы сортировки и их реализации на Python. Для сравнения их производительности мы будем рассматривать задачу с сайта Leetcode о сортировке массива. Размеры данных этой задачи ограничены следующим образом:
Мы решили эту задачу при помощи всех известных алгоритмов сортировки. Вот какие у нас получились результаты:
Сортировка методом пузырька
Это самый простой алгоритм сортировки. В процессе его выполнения мы перебираем наш список и на каждой итерации сравниваем элементы попарно. При необходимости элементы меняются местами, чтобы больший элемент отправлялся в конец списка.
Сортировка выбором
В этом алгоритме мы создаем два сегмента нашего списка: один отсортированный, а другой несортированный.
В процессе выполнения алгоритма мы каждый раз удаляем самый маленький элемент из несортированного сегмента списка и добавляем его в отсортированный сегмент. Мы не меняем местами промежуточные элементы. Следовательно, этот алгоритм сортирует массив с минимальным количеством перестановок.
Сортировка вставками
Подобно алгоритму сортировки выбором, мы делим наш список на две части. Далее мы перебираем неотсортированную часть и вставляем каждый элемент из данного сегмента на его правильное место в отсортированной части списка.
Марк Лутц «Изучаем Python»
Скачивайте книгу у нас в телеграм
Сортировка Шелла
Сортировка Шелла является оптимизированным вариантом сортировки вставками.
Оптимизация достигается путем сравнения не только соседних элементов, но и элементов на определенном расстоянии, которое в течении работы алгоритма уменьшается. На последней итерации это расстояние равно 1. После этого алгоритм становится обычным алгоритмом сортировки вставками, что гарантирует правильный результат сортировки.
Но следует отметить один момент: к тому времени, когда это произойдет, наш массив будет почти отсортирован, поэтому итерации будут выполнятся очень быстро.
Пирамидальная сортировка («сортировка кучей»)
Как и в двух предыдущих алгоритмах, мы создаем два сегмента списка: отсортированный и несортированный.
В данном алгоритме для эффективного нахождения максимального элемента в неотсортированной части списка мы используем структуру данных «куча».
Метод heapify в примере кода использует рекурсию для получения элемента с максимальным значением на вершине.
Сортировка слиянием
Этот алгоритм работает по принципу «разделяй и властвуй».
Здесь мы делим список ровно пополам и продолжаем это делать, пока в нем не останется только один элемент. Затем мы объединяем уже упорядоченные части нашего списка. Мы продолжаем это делать, пока не получим отсортированный список со всеми элементами несортированного входного списка.
Быстрая сортировка
В этом алгоритме мы разбиваем список при помощи опорного элемента, сортируя значения вокруг него.
В нашей реализации мы выбрали опорным элементом последний элемент массива. Наилучшая производительность достигается тогда, когда опорный элемент делит список примерно пополам.
Сортировка подсчетом
Этот алгоритм не производит сравнение элементов. Для сортировки используются математические свойства целых чисел. Мы подсчитываем вхождения числа в массиве и сохраняем результат во вспомогательном массиве, где индексу соответствует значение ключа.
Следует также упомянуть поразрядную сортировку, которая использует сортировку подсчетом либо блочную (корзинную) сортировку в качестве подпрограммы. Этот метод сортировки заслуживает отдельной статьи для разбора.
Для удобства соберем весь наш код вместе:
Мы нашли потрясающий плейлист, в котором алгоритмы сортировки демонстрируются при помощи народного танца. Посмотрите это видео, оно того стоит!
В нашем небольшом исследовании мы изучили различные алгоритмы сортировки и определили время их выполнения, а также их потребности в памяти. Теперь мы понимаем, что значит время выполнения, стабильность алгоритма и используемая память. Чтобы выбрать подходящий алгоритм, мы должны оценивать эти параметры. Также, для создания более эффективных решений, типа Timsort, мы можем комбинировать наши базовые алгоритмы.