Самый простой способ сделать "естественную" сортировку чисел в строках?
Я только что видел это, и мне интересно, каков наилучший способ реализовать естественную сортировку, как это?
Обычно в списке 1,4,11,12
сортировка строк (используется в элементах списка) возвращает 1,11,12,4
, Как мне реализовать естественный порядок?
3 ответа
Предметы также могут быть
[ 'screen 4 episode 13', 'screen 11 episode 1', .... ]
Для приведенного выше списка и примера списка, приведенного в вопросе, можно использовать следующий метод:
Преобразуйте число в элементах в систему на основе сегмента, то есть вычислите максимум цифры в любой строке. Например, в приведенном выше списке значение равно 2. Теперь преобразуйте числа в элементах так, чтобы их длина оказалась такой же, как и максимальная. Следовательно, "эпизод 13 экрана 4" будет преобразован в "эпизод 13 экрана 04", а "эпизод 1 экрана 11" будет преобразован в "эпизод 01 экрана 11".
Теперь сортируйте измененный список как строку.
Эффективное решение состоит в том, чтобы сгенерировать для каждой строки для сортировки ключ, который можно сравнить лексикографически, а затем использовать эти ключи для сортировки исходных строк.
Чтобы сгенерировать эти ключи, начните с копии исходных строк, а затем преобразуйте подстроки, представляющие числа, следующим образом:
- Удалите все ведущие нули.
- Подготовьте длину подстроки цифр, закодированную в виде цифры "9", повторенной int(len/9) раз, за которой следует цифра, представляющая len % 9.
Например:
1 -> 11
10 -> 210
9 -> 19
12345678 -> 812345678
987654321 -> 90987654321 // len = 9, int(len / 9) = 1, len % 9 = 0
9876543210 -> 919876543210 // len = 10, int(len / 9) = 1, len % 9 = 1
Вы также можете заменить знаки препинания на клавишах, чтобы "Foo 123" и "Foo-123" сравнивались одинаково.
Модуль Perl Sort::Key::Natural использует этот подход.
Вы можете разбить каждую строку на последовательность токенов. Токен состоит из всех не цифр или всех цифр. Затем выполните сравнение по последовательности токенов, а не по последовательности символов в строке. Токены без цифр сравниваются как строки, токены без цифр сравниваются друг с другом, используя их целочисленные значения.
Это зависит от вас, как все-цифровые токены сравниваются с не-цифровыми токенами, но, скорее всего, вы хотите foo123.txt
появляться после foo.txt
но прежде fooA.txt
, Это означает, что при сравнении токена foo
против знака foo<something>
, вы не получите ответ сразу, основываясь только на этих двух токенах - вам нужно сравнить <something>
против токена следующего foo
,
Затем этот базовый подход можно оптимизировать, чтобы гарантировать, что вы не будете больше разбивать строки, чем это строго необходимо.