不幸的是,上面的代碼不起作用。
它看起來像它的工作。畢竟,您明確要求按字符串比較排序,並且根據字符串比較,"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