2009-12-21 95 views
3

有沒有人在Emacs Lisp中實現自然順序排序?我知道寫作並不難,但借用別人的作品更容易。Emacs Lisp的自然順序排序

(是的,我不能相信我只是搜索Emacs的功能,無法找到它。)

回答

4

此代碼提供可在排序算法中使用的'dictionary-lessp。好像在我的測試工作至今:

(defun dictionary-lessp (str1 str2) 
    "return t if STR1 is < STR2 when doing a dictionary compare 
(splitting the string at numbers and doing numeric compare with them)" 
    (let ((str1-components (dict-split str1)) 
     (str2-components (dict-split str2))) 
    (dict-lessp str1-components str2-components))) 

(defun dict-lessp (slist1 slist2) 
    "compare the two lists of strings & numbers" 
    (cond ((null slist1) 
     (not (null slist2))) 
     ((null slist2) 
     nil) 
     ((and (numberp (car slist1)) 
       (stringp (car slist2))) 
     t) 
     ((and (numberp (car slist2)) 
       (stringp (car slist1))) 
     nil) 
     ((and (numberp (car slist1)) 
       (numberp (car slist2))) 
     (or (< (car slist1) (car slist2)) 
      (and (= (car slist1) (car slist2)) 
        (dict-lessp (cdr slist1) (cdr slist2))))) 
     (t 
     (or (string-lessp (car slist1) (car slist2)) 
      (and (string-equal (car slist1) (car slist2)) 
        (dict-lessp (cdr slist1) (cdr slist2))))))) 

(defun dict-split (str) 
    "split a string into a list of number and non-number components" 
    (save-match-data 
    (let ((res nil)) 
     (while (and str (not (string-equal "" str))) 
     (let ((p (string-match "[0-9]*\\.?[0-9]+" str))) 
      (cond ((null p) 
       (setq res (cons str res)) 
       (setq str nil)) 
       ((= p 0) 
       (setq res (cons (string-to-number (match-string 0 str)) res)) 
       (setq str (substring str (match-end 0)))) 
       (t 
       (setq res (cons (substring str 0 (match-beginning 0)) res)) 
       (setq str (substring str (match-beginning 0))))))) 
     (reverse res)))) 

這是我的測試:

(and (dictionary-lessp "a" "b") 
    (null (dictionary-lessp "b" "a")) 
    (null (dictionary-lessp "a" "a")) 
    (dictionary-lessp "1" "2") 
    (null (dictionary-lessp "2" "1")) 
    (null (dictionary-lessp "1" "1")) 
    (dictionary-lessp "1" "a") 
    (null (dictionary-lessp "a" "1")) 
    (dictionary-lessp "" "a") 
    (null (dictionary-lessp "a" "")) 

    (dictionary-lessp "ab12" "ab34") 
    (dictionary-lessp "ab12" "ab123") 
    (dictionary-lessp "ab12" "ab12d") 
    (dictionary-lessp "ab132" "ab132z") 


    (dictionary-lessp "132zzzzz" "ab132z") 
    (null (dictionary-lessp "1.32" "1ab"))) 

使用例子是:

(sort '("b" "a" "1" "f19" "f" "f2" "f1can") 'dictionary-lessp) 

產量

("1" "a" "b" "f" "f1can" "f2" "f19") 
+0

這是真棒,謝謝! P.S.,我想你忘了一個;;在「p!= 0」之前。 – Ken 2009-12-21 21:36:46

+0

我不明白評論,你在說什麼檢查? – 2009-12-21 22:28:23

+0

文本「p!= 0」看起來像一個評論(在COND裏沒有任何意義),但是在它之前沒有評論標記。 – Ken 2009-12-22 01:30:18