kucha007 发表于 2023-12-4 21:43:33

【K:AnalNum4STR】含数字的字符串排序(类似Windows排序)

本帖最后由 kucha007 于 2023-12-4 22:45 编辑

该函数可在字符串的数字前面加"0",使得字符串中的数字部分强制满足位数
从而可以用于对文件名等含数字的字符串进行排序,排序结果类似Windows

该函数最早的灵感来自帖子:http://www.theswamp.org/index.php?topic=16564.0
我在这篇帖子思路的基础上,针对CAD高版本做了点优化,并且将字符串先拆分成单字再找数字。
在函数规整数字的过程中,我还去除了字符串中的空格和各种括号,这些对象一般也不用作排序依据
目前函数已经实际运用在这个程序中:http://bbs.mjtd.com/thread-188813-1-1.html


分享给大家,欢迎大家继续改进。
;分析字符串中的数字,强制满足位数并返回(在数字前加上0)
(defun K:AnalNum4STR (Count STR / K:ExplodeSTR2One RtnSTR NumLst STRLst CurSTR TotNum TmpSTR)
;将字符串拆分成单字符列表
(defun K:ExplodeSTR2One (STR / RtnSTR)
    (while (> (strlen STR) 0)
      (cond
      ((> (ascii (substr STR 1 1)) 128) ;大于128为汉字
          (if
            (and
            (>= (atoi (substr (ver) 13)) 2021)
            (/= (getvar "lispsys") 0)
            )
            (progn
            (setq RtnSTR (cons (substr STR 1 1) RtnSTR))
            (setq STR (substr STR 2))
            )
            (progn
            (setq RtnSTR (cons (substr STR 1 2) RtnSTR))
            (setq STR (substr STR 3))
            )
          )
      )
      (T
          (setq RtnSTR (cons (substr STR 1 1) RtnSTR))
          (setq STR (substr STR 2))
      )
      )
    )
    (reverse RtnSTR)
)
(if (and STR (= 'STR (type STR)))
      (progn
          (setq RtnSTR ""
                NumLst (list "0" "1" "2" "3" "4" "5" "6" "7" "8" "9")
                STRLst (K:ExplodeSTR2One STR)
          )
          (while STRLst
            (setq CurSTR (car STRLst)
                  STRLst (cdr STRLst)
            )
            (if (member CurSTR NumLst);找到了数字
                (progn
                  (setq TotNum 1);数字连续的次数
                  (while (member (setq TmpSTR (car STRLst)) NumLst);下一个也是数字
                        (setq TotNum (1+ TotNum)
                              STRLst (cdr STRLst)
                              CurSTR (strcat CurSTR TmpSTR)
                        )
                  )
                  (repeat (- Count TotNum)
                        (setq CurSTR (strcat "0" CurSTR))
                  );不足位数前面加零
                  (setq RtnSTR (strcat RtnSTR CurSTR))
                )
                (if (not (member CurSTR '(" " "(" ")" "(" ")" "[" "]" "{" "}" "【" "】")));移除空格和括号
                  (setq RtnSTR (strcat RtnSTR CurSTR))
                )
            )
            )
      )
)
RtnSTR
)
函数用法:

(K:AnalNum4STR 5 "PN375-A10.dwg")
;返回:"PN00375-A00010.dwg"


排序用法:
;假设我们的有一个表
(setq DataLst (list "A9.DWG" "A1.DWG" "A10.DWG" "B11.DWG" "B2.DWG" "B05.DWG"))

(setq DataLst (vl-sort DataLst '(lambda (x y) (< x y))))
;直接排序将得到错误的结果
;返回:("A1.DWG" "A10.DWG" "A9.DWG" "B05.DWG" "B11.DWG" "B2.DWG")

(setq DataLst (vl-sort DataLst
                     '(lambda (x y)
                        (< (K:AnalNum4STR 5 x) (K:AnalNum4STR 5 y))
                        )
            )
)
;使用函数处理后排序将得到我们想要的结果
;返回:("A1.DWG" "A9.DWG" "A10.DWG" "B2.DWG" "B05.DWG" "B11.DWG")









sncokina 发表于 2023-12-5 08:34:06

感谢分享,看上去很实用。。

lxl217114 发表于 2023-12-5 09:57:50

感谢分享,谢谢大佬发布新品。

magicheno 发表于 2023-12-5 14:22:34

感谢大佬分享分享

你有种再说一遍 发表于 2023-12-5 18:30:42

微软应该是用红黑树实现的

Qwer1243 发表于 2024-5-5 11:51:45

感谢楼主的分享,代码很好用
页: [1]
查看完整版本: 【K:AnalNum4STR】含数字的字符串排序(类似Windows排序)