不幸的是,上面的代码不起作用。
它看起来像它的工作。毕竟,您明确要求按字符串比较排序,并且根据字符串比较,"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"
&RIGHTARROW; (12 ".txt")
),然后将这些名单按字典与类型之间的顺序进行排序(如字符串前数字) ,并在每种类型中进行排序。
这是我曾经写过的一个版本:https://gist.github。com/lispm/e028d3f3c11c9f74d4e7 – 2014-12-05 14:17:13
顺便说一句,当我们在REPL中使用文字数据时,应该大部分时间都可以。 REPL通常会创建新的新数据。您会在REPL使用中看到问题吗? – 2014-12-05 14:20:48
如果你在SBCL中评估'(defun foo()(sort'(1 2 3)'<))',你会得到十一行警告文字数据的破坏性修改。既然你得到了你期望的行为,那么在REPL中这可能不算什么大事,但是良好的习惯很少会带来很好的习惯。 – 2014-12-05 15:16:22