我有一个字符串,下划线分隔单词(例如 aaa_bbb_ccc )
我创建了一个将字符串转换为camelCase的函数(例如 aaaBbbCcc )。
我想知道是否有一些我做错了会影响性能的事情。这是代码:
(defun underscore-to-camel (input)
(defparameter input-clean-capitalized (remove #\_ (string-capitalize input)))
(setf (aref input-clean-capitalized 0) (aref (string-downcase (aref input-clean-capitalized 0)) 0))
input-clean-capitalized)
我还创建了第二个变体但速度慢了约25%(使用time
测量了300万次执行):
(defun underscore-to-camel-v2 (input)
(defparameter input-clean-capitalized (remove #\_ (string-capitalize input)))
(concatenate
'string
(string-downcase (aref input-clean-capitalized 0))
(subseq input-clean-capitalized 1)))
答案 0 :(得分:3)
首先,defparameter不是你想要使用的。你应该真的重构 你的代码是这样的:
(defun underscore-to-camel (input)
(let ((input-clean-capitalized (remove #\_ (string-capitalize input))))
(setf (aref input-clean-capitalized 0)
(aref (string-downcase (aref input-clean-capitalized 0)) 0))
input-clean-capitalized))
第二:你可以像这样解决问题:
(defun underscore-to-camel-eff (input)
(declare (optimize (debug 1) (speed 3) (safety 1)))
(loop :with length = (length input)
:with i = 0
:while (< i length)
:for c = (aref input i)
:if (or (= i (- length 1))
(char/= c #\_))
:collect (prog1 c (incf i)) :into result
:else
:collect (prog1
(char-upcase (aref input (+ i 1)))
(incf i 2))
:into result
:finally (return (concatenate 'string result))))
使用SBCL在我的电脑上运行,只需要一半的解决时间。
这是一个使用正则表达式的解决方案,虽然比任何其他解决方案都慢:
(defun underscore-to-camel-ppcre (input)
(declare (optimize (debug 1) (speed 3) (safety 1)))
(ppcre:regex-replace-all "_([a-z])"
input
(lambda (target-string
start
end
match-start
match-end
reg-starts
reg-ends)
(declare (ignore start
end
match-end
reg-starts
reg-ends))
(string
(char-upcase
(aref target-string (+ 1 match-start)))))))
必要的包称为“ppcre”。 您可以通过
安装它(ql:quickload "cl-ppcre")
一旦你去了http://www.quicklisp.org/beta/并安装了quicklisp。
答案 1 :(得分:2)
我建议使用字符级功能。他们从char-
开始。然后你可以摆脱STRING-DOWNCASE
和&#34; CONCATENATE`。
DEFPARAMETER
不用于局部变量。使用LET
。
但是一个简单的版本是这样的:
(defun underscore-to-camel (input)
(string-downcase (remove #\_ (string-capitalize input))
:start 0
:end 1))
答案 2 :(得分:2)
另一种方法:
(defun underscore-to-camel (input)
(with-output-to-string (s)
(loop
:for c :across input
:for upcase := (char= c #\_) :then (or upcase (char= c #\_)) :do
(cond
((char= c #\_))
(upcase (write-char (char-upcase c) s) (setf upcase nil))
(t (write-char c s))))))
答案 3 :(得分:2)
用SBCL试验一段时间后,这是我找到的最快的版本
(defun camelcase (s)
(do* ((n (length s))
(i 0 (the fixnum (1+ i)))
(wp 0)
(target (make-array n :element-type 'character)))
((>= i n) (subseq target 0 wp))
(declare (fixnum n i wp)
(string s))
(if (and (< i (the fixnum (1- n)))
(char= (char s i) #\_)
(char>= (char s (the fixnum (1+ i))) #\a)
(char<= (char s (the fixnum (1+ i))) #\z))
(setf (aref target (1- (the fixnum (incf wp))))
(code-char (- (char-code (char s (the fixnum (incf i)))) 32)))
(setf (aref target (1- (the fixnum (incf wp))))
(char s i)))))
而不是调用#'char-upcase
我只是减去32,因为已知该字符位于a
- z
范围内,而我正在假设ASCII编码。这削弱了一些周期。
由于某些原因,我不明白显式数组填充比使用vector-push
更快。