К сожалению, приведенный выше код не работает.
Похоже, что сработало. В конце концов, вы явно попросили сортировать по сравнение строк, и в соответствии с сравнением строк "2.txt"
находится между "13.txt"
и "23.txt"
. Если вы хотите отсортировать численно, вы можете использовать ключевую функцию, которая будет читать номер с начала строки. Кроме того, сортировка является разрушительной, поэтому вы не должны использовать ее в буквальных данных (например, в цитированном списке).
Во всяком случае, это не слишком сложно, чтобы сплести что-то, что позволит вам сортировать сортировку, которую вы ищете. Вот определение для естественно-струна-lessp функции:
(defun natural-string-lessp (a b)
(multiple-value-bind (ai aend)
(parse-integer a :junk-allowed t)
(multiple-value-bind (bi bend)
(parse-integer b :junk-allowed t)
(or (and ai
(or (not bi)
(and bi
(or (< ai bi)
(and (= ai bi)
(string-lessp a b :start1 aend :start2 bend))))))
(and (not ai)
(not bi)
(string-lessp a b))))))
Он обрабатывает только ведущие числа, а не числа в середине строки, так, например, "a-100-foo.txt"
будет еще прийти до "a-3-foo.txt"
, но этого может быть достаточно для ваших нужд. Вот пример его использования:
(let ((sss (copy-list '("1.txt" "10.txt" "13.txt" "12.txt"
"2.txt" "23.txt"))))
(sort sss #'natural-string-lessp))
;=> ("1.txt" "2.txt" "10.txt" "12.txt" "13.txt" "23.txt")
Документация parse-integer и именованные аргументы для string-lessp может быть полезным.
Более надежная реализация будет понять, как превратить каждую строку в последовательность строк и чисел (например, "12.txt"
& СтрелкаВправо; (12 ".txt")
), а затем отсортировать эти списки лексически с упорядочением среди типов (например, числа до строк) , и с упорядочением в каждом типе.
Вот версия, которую я когда-то писал: https: //gist.github.com/lispm/e028d3f3c11c9f74d4e7 –
Кстати, когда мы используем литеральные данные в REPL, это должно быть в большинстве случаев в порядке. REPL обычно создает новые свежие данные. Вы видите проблему с использованием REPL? –
Если вы оцениваете '(defun foo() (sort '(1 2 3)' <))' в SBCL, вы получите одиннадцать строк предупреждения о деструктивной модификации литералов. Так как вы получаете такое поведение, которое вы ожидаете, это, вероятно, не столь большая сделка в REPL, но хорошие привычки с небольшим успехом могут привести к хорошим привычкам. –