You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写优雅的Elisp函数实现驼峰转大写蛇形命名?现有实现待优化

改进方案

现有实现的主要问题

  • 递归实现无尾优化,长字符串容易触发栈溢出
  • 递归中反复调用concat,字符串不可变特性导致O(n²)的时间复杂度
  • 自定义的upcasep判断有误:会将数字、符号等非大写字母判定为大写,错误插入下划线(比如isFailed2Upgrade会被转成IS_FAILED_2_UPGRADE)
  • 未处理连续大写缩写场景(比如HTTPServer会被转成H_T_T_P_SERVER)

基础优化实现

核心转换逻辑用迭代+字符列表累积,替代原递归实现,效率提升明显,完全符合你给出的示例需求:

(defun change-case-helper (text)
  "将驼峰风格的TEXT转换为全大写下划线分隔的蛇形格式"
  (let ((result nil)
        (len (length text)))
    (dotimes (i len)
      (let ((c (aref text i)))
        ;; 非首字符位置遇到大写字母,前面插入下划线
        (when (and (> i 0) (upper-case-p c))
          (push ?_ result))
        ;; 统一转大写后加入结果列表
        (push (upcase c) result)))
    ;; 逆序列表后一次性拼接为字符串
    (concat (nreverse result))))

你原有的主函数change-case无需修改,选中区域/光标取符号的逻辑已经很完善,直接替换上述helper即可运行。
该实现的优势:

  • 用列表操作替代多次concat,时间复杂度从O(n²)降到O(n)
  • 用Emacs内置的upper-case-p判断大写,自动兼容多字节字符,无自定义判断的边界bug
  • 仅在非首字符的大写前插入下划线,避免开头多余的冗余下划线

进阶适配缩写场景

如果需要处理连续大写的缩写场景(比如HTTPServer转HTTP_SERVER、ParseJSONString转PARSE_JSON_STRING),可以调整判断条件,仅当大写字母的前一位是小写、或后一位是小写时才插入下划线:

(defun change-case-helper (text)
  "转换驼峰为大写下划线蛇形,兼容连续大写缩写"
  (let ((result nil)
        (len (length text)))
    (dotimes (i len)
      (let* ((c (aref text i))
             (prev-c (if (> i 0) (aref text (1- i)) nil))
             (next-c (if (< i (1- len)) (aref text (1+ i)) nil)))
        ;; 非首字符的大写,满足前一位是小写/后一位是小写时,前插下划线
        (when (and (> i 0)
                   (upper-case-p c)
                   (or (lower-case-p prev-c)
                       (lower-case-p next-c)))
          (push ?_ result))
        (push (upcase c) result)))
    (concat (nreverse result))))

该版本对常见驼峰命名的转换效果更符合实际使用习惯,不会把连续的大写缩写拆分成单个字符分隔的格式。

内容的提问来源于stack exchange,提问作者fast tooth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.26 21:06:03