emacs - Emacs Lisp 的自然顺序排序

标签 emacs elisp natural-sort

有人在 Emacs Lisp 中实现了自然顺序排序吗?我知道这不难写,但借用别人的作品更容易。

(是的,我无法相信我刚刚搜索了一个 Emacs 函数却找不到它。)

最佳答案

此代码提供了一个可用于排序算法的'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")

关于emacs - Emacs Lisp 的自然顺序排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1942045/

相关文章:

R:gtools混合排序的意外自然排序

sql - Microsoft SQL Server 中的自然(人类字母数字)排序

ruby - 如何对给定的数组列表进行排序?

emacs - 如何获得给定emacs命令的键盘快捷键?

emacs - Ipython shell 无法启动

Emacs 点对语法改进

emacs - 修改 fortran 中注释的 emacs 缩进行为

emacs - 有没有办法在emacs中撤消split-window-below?

emacs - 有没有更好的方法让 emacs 自动完成插件知道库的(例如 Ring、compojure)关键字?

emacs - 如何在 Emacs 中打开 native cmd.exe 窗口