按「姓氏笔画」排序

刚才看到 一条新闻 提及用姓氏笔画排序,Emacs 似乎没有现成的方案,所以我自己实现了个:

(setq some-names [习近平 李克强 栗战书 汪洋 王沪宁 赵乐际 韩正])

(sort (copy-sequence some-names)
      (lambda (a b)
        (< (unihan-strokes (aref (symbol-name a) 0))
           (unihan-strokes (aref (symbol-name b) 0)))))
     => [习近平 王沪宁 李克强 汪洋 赵乐际 栗战书 韩正]

笔画数据来源于 Unicode 的 Unihan Database

;; Unihan Database: http://www.unicode.org/charts/unihan.html
;; Documentation:   http://www.unicode.org/reports/tr38/
;; Download:        http://www.unicode.org/Public/UCD/latest/ucd/Unihan.zip

(defvar unihan-db
  (let ((table (make-hash-table)))
    (with-temp-buffer
      (insert-file-contents "~/Downloads/Unihan/Unihan_DictionaryLikeData.txt")
      (goto-char (point-min))
      (while (re-search-forward
              ;; http://www.unicode.org/reports/tr38/#kTotalStrokes
              ;; 格式如下,以「中」为例
              ;; U+4E2D	kTotalStrokes	4
              ;; 目前唯一的例外是「范」字,CN 8 画,TW 9 画
              ;; U+8303	kTotalStrokes	8 9
              (rx line-start
                  "U+" (group (1+ hex))
                  space "kTotalStrokes" space
                  (group (1+ digit)) (0+ space (1+ digit))
                  line-end)
              nil t)
        (let ((char (read (concat "#x" (match-string 1))))
              (strokes (read (match-string 2))))
          (puthash char strokes table))))
    table)
  "汉字笔画数据.")

(defun unihan-strokes (char)
  "返回汉字 CHAR 的笔画."
  (gethash char unihan-db))

(unihan-strokes ?中)
     => 4

另外一个有趣的发现是 习近平 李克强 栗战书 汪洋 王沪宁 赵乐际 韩正 这个顺序恰好就是姓氏的 Unicode Codepoint 的顺序

some-names
     => [习近平 李克强 栗战书 汪洋 王沪宁 赵乐际 韩正]

(sort (copy-sequence some-names)
      (lambda (a b)
        (< (aref (symbol-name a) 0)
           (aref (symbol-name b) 0))))
     => [习近平 李克强 栗战书 汪洋 王沪宁 赵乐际 韩正]

好一个巧。

2 个赞

CJK Unified Ideographs 上图的红色区域(占据BMP大约1/3)定义了两万多个汉字,其中前20,902个汉字是按照《康熙字典》里笔画顺序排列的。

http://blog.fpliu.com/it/data/text/charset/Unicode