Используя Python 3.x, у меня есть список строк, для которых я хотел бы выполнить естественную сортировку по алфавиту.
Естественная сортировка: порядок сортировки файлов в Windows.
Например, следующий список естественно отсортирован (что я хочу):
['elm0', 'elm1', 'Elm2', 'elm9', 'elm10', 'Elm11', 'Elm12', 'elm13']
И вот «отсортированная» версия приведенного выше списка (что у меня есть):
['Elm11', 'Elm12', 'Elm2', 'elm0', 'elm1', 'elm10', 'elm13', 'elm9']
Я ищу функцию сортировки, которая ведет себя как первая.
python
sorting
python-3.x
snakile
источник
источник
!1, 1, !a, a
. Похоже, что единственный способ получить сортировку, подобный Windows, - это использоватьStrCmpLogicalW
саму функцию Windows , поскольку никто, кажется, не реализовал эту функцию правильно (источник был бы признателен). Решение: stackoverflow.com/a/48030307/2441026Ответы:
Для этого в PyPI есть сторонняя библиотека natsort (полное раскрытие, я автор пакета). Для вашего случая вы можете выполнить одно из следующих действий:
Вы должны заметить, что он
natsort
использует общий алгоритм, поэтому он должен работать практически со всеми входными данными, которые вы к нему добавляете. Если вы хотите получить более подробную информацию о том, почему вы можете выбрать библиотеку для этого, а не использовать собственную функцию, посетите страницуnatsort
документации, как это работает , в частности, « Особые случаи везде»! раздел.Если вам нужен ключ сортировки вместо функции сортировки, используйте одну из следующих формул.
источник
natsort
также «естественно» обрабатывает случай нескольких отдельных чисел в строках. Отличный материал!Попробуй это:
Вывод:
Код, адаптированный здесь: Сортировка для людей: Порядок естественной сортировки .
источник
return sorted(l, key)
вместоl.sort(key)
? Это для увеличения производительности или просто чтобы быть более питоническим?re.split('([0-9]+)', '0foo')
возвращается['', '0', 'foo']
. Из-за этого строки всегда будут на четных индексах и целые на нечетных индексах в массиве.Вот гораздо более питонная версия ответа Марка Байера:
Теперь эта функция может быть использована в качестве ключа в любой функции , которая использует его, как
list.sort
,sorted
,max
и т.д.Как лямбда
источник
Я написал функцию, основанную на http://www.codinghorror.com/blog/2007/12/sorting-for-humans-natural-sort-order.html, которая добавляет возможность по-прежнему передавать свой собственный параметр «ключ». Мне это нужно для того, чтобы выполнять естественную сортировку списков, которые содержат более сложные объекты (не только строки).
Например:
источник
natural_sort_key
, а затем при сортировке списка вы можете связать ключи, например:list.sort(key=lambda el: natural_sort_key(el['name']))
Давайте проанализируем данные. Разрядность всех элементов равна 2. И есть 3 буквы в общей буквенной части
'elm'
.Таким образом, максимальная длина элемента равна 5. Мы можем увеличить это значение, чтобы убедиться (например, до 8).
Учитывая это, у нас есть однострочное решение:
без регулярных выражений и внешних библиотек!
Объяснение:
источник
width = max(data, key=len)
для вычисления того, что нужно8
'{0:0>{width}}'.format(x, width=width)
Дано:
Подобно решению SergO, 1-вкладыш без внешних библиотек будет :
или
Объяснение:
Это решение использует ключевую особенность сортировки чтобы определить функцию, которая будет использоваться для сортировки. Поскольку мы знаем, что каждой записи данных предшествует 'elm', функция сортировки преобразует целую часть строки после 3-го символа (т. Е. Int (x [3:])). Если числовая часть данных находится в другом месте, то эту часть функции придется изменить.
ура
источник
Существует множество реализаций, и, хотя некоторые из них приблизились, ни одна из них не отразила элегантность, которую предоставляет современный питон.
Осторожно при использовании
from os.path import split
Вдохновение от
источник
Значение этого поста
Я хочу предложить решение без регулярных выражений, которое можно применять в целом.
Я создам три функции:
find_first_digit
который я позаимствовал у @AnuragUniyal . Он найдет позицию первой цифры или не цифры в строке.split_digits
который является генератором, который разбирает строку на цифры и не цифры. Он также будетyield
целым числом, когда это цифра.natural_key
просто заворачиваетsplit_digits
вtuple
. Это то , что мы используем в качестве ключа дляsorted
,max
,min
.функции
Мы можем видеть, что в общем случае мы можем иметь несколько цифр:
Или оставьте с учетом регистра:
Мы видим, что он сортирует список ОП в соответствующем порядке.
Но он может обрабатывать и более сложные списки:
Мой эквивалент регулярного выражения будет
источник
Один из вариантов - превратить строку в кортеж и заменить цифры, используя расширенную форму http://wiki.answers.com/Q/What_does_expanded_form_mean
таким образом a90 станет ("a", 90,0) и a1 станет ("a", 1)
ниже приведен пример кода (который не очень эффективен из-за способа удаления начальных 0 из чисел)
вывод:
источник
('b', 1) < ('b', 'e', 't', 'a', 1, '.', 1)
вернетсяTypeError: unorderable types: int() < str()
natsort
, естественная альтернатива , pypi.org/project/natsortОсновываясь на ответах здесь, я написал
natural_sorted
функцию, которая ведет себя как встроенная функцияsorted
:Исходный код также доступен в моем хранилище фрагментов GitHub: https://github.com/bdrung/snippets/blob/master/natural_sorted.py
источник
Приведенные выше ответы хороши для показанного конкретного примера , но пропускают несколько полезных случаев для более общего вопроса естественной сортировки. Я только что попал в один из этих случаев, поэтому создал более тщательное решение:
Тестовый код и несколько ссылок (вкл и выкл StackOverflow) находятся здесь: http://productarchitect.com/code/better-natural-sort.py
Обратная связь приветствуется. Это не должно быть окончательным решением; просто шаг вперед.
источник
natsorted
иhumansorted
терпите неудачу, потому что они использовались неправильно ... вы пытались передать егоnatsorted
как ключ, но на самом деле это была сама функция сортировки. Вы должны были попробоватьnatsort_keygen()
.Скорее всего,
functools.cmp_to_key()
он тесно связан с базовой реализацией сортировки Python. Кроме того, параметр cmp является устаревшим. Современный способ заключается в преобразовании входных элементов в объекты, которые поддерживают требуемые операции расширенного сравнения.В CPython 2.x объекты разнородных типов могут быть упорядочены, даже если соответствующие операторы расширенного сравнения не были реализованы. В CPython 3.x объекты разных типов должны явно поддерживать сравнение. Посмотрите, как Python сравнивает строку и int? какие ссылки на официальную документацию . Большинство ответов зависят от этого неявного порядка. Переход на Python 3.x потребует нового типа для реализации и унификации сравнений между числами и строками.
Есть три разных подхода. Первый использует вложенные классы, чтобы использовать преимущества
Iterable
алгоритма сравнения Python . Второй разворачивает это вложение в один класс. Третий отказывается от подклассов,str
чтобы сосредоточиться на производительности. Все рассчитано; второй в два раза быстрее, а третий почти в шесть раз быстрее. Подклассыstr
не требуются, и, вероятно, изначально были плохой идеей, но они имеют определенные удобства.Символы сортировки дублируются, чтобы принудительно упорядочить регистр, и меняются регистром для принудительной сортировки букв нижнего регистра; это типичное определение «натуральный сорт». Я не мог определиться с типом группировки; некоторые могут предпочесть следующее, что также дает значительные преимущества в производительности:
Там, где они используются, операторы сравнения устанавливаются так, что
object
они не будут игнорироватьсяfunctools.total_ordering
.Естественная сортировка довольно сложна и неопределенно определяется как проблема. Не забудьте запустить
unicodedata.normalize(...)
заранее, и рассмотреть вопрос об использовании,str.casefold()
а неstr.lower()
. Возможно, есть тонкие проблемы с кодированием, которые я не рассматривал. Поэтому я рекомендую библиотеку natsort . Я быстро взглянул на хранилище github; обслуживание кода было звездным.Все алгоритмы, которые я видел, зависят от таких хитростей, как дублирование и понижение символов, а также от случая замены. Хотя это удваивает время выполнения, альтернатива потребует полного естественного упорядочения во входном наборе символов. Я не думаю, что это является частью спецификации Unicode, и так как у Unicode гораздо больше цифр, чем
[0-9]
создание такой сортировки, было бы одинаково сложно. Если вы хотите сравнения сlocale.strxfrm
учетом локали, подготовьте свои строки в соответствии с сортировкой Python HOW TO .источник
Позвольте мне представить свой взгляд на эту потребность:
Теперь, если у нас есть такой список:
Мы можем просто использовать
key=
kwarg для естественной сортировки:Недостаток здесь, конечно, как и сейчас, функция будет сортировать заглавные буквы перед строчными.
Я оставлю реализацию нечувствительного к регистру групера читателю :-)
источник
Я предлагаю вам просто использовать
key
ключевое слово аргументsorted
для достижения желаемого списка.Например:
источник
a_51
будет послеa500
, хотя 500> 51После ответа @Mark Byers приведена адаптация, которая принимает этот
key
параметр и является более совместимой с PEP8.Я также сделал Gist
источник
key
параметр? Но это также иллюстрируется в ответе @ beauburrierУлучшение в улучшении Клаудиу по ответу Марка Байера ;-)
Кстати, может быть, не все помнят, что значения по умолчанию для аргументов функции оцениваются по
def
времениисточник
Благодарности :
Bubble Sort Домашнее задание
Как читать строку по одной букве за раз в Python
источник
источник