String 按分隔符拆分字符串并包含分隔符-Common Lisp
如何在Common Lisp中用分隔符分割字符串,就像在split-SEQUENCE中那样,但同时在字符串列表中添加分隔符 例如,我可以写:String 按分隔符拆分字符串并包含分隔符-Common Lisp,string,split,common-lisp,String,Split,Common Lisp,如何在Common Lisp中用分隔符分割字符串,就像在split-SEQUENCE中那样,但同时在字符串列表中添加分隔符 例如,我可以写: (使用分隔符拆分字符串#\“a.bc.def.com”) 结果将是(“a”、“bc”、“def”、“com”) 我尝试了以下代码(生成可调整字符串生成可使用向量推送扩展扩展的字符串): (定义可调字符串) (制作数组(长度为s) :填充指针(长度s) :可调t :初始内容 :元素类型(数组元素类型s))) (defun split str(字符串和键(分隔
(使用分隔符拆分字符串#\“a.bc.def.com”)
结果将是(“a”、“bc”、“def”、“com”)
我尝试了以下代码(生成可调整字符串
生成可使用向量推送扩展
扩展的字符串):
(定义可调字符串)
(制作数组(长度为s)
:填充指针(长度s)
:可调t
:初始内容
:元素类型(数组元素类型s)))
(defun split str(字符串和键(分隔符#\)(保持分隔符为零))
将字符串拆分为字符串列表,且分隔符保持不变
在结果列表中。”
(让((零字)
(当前单词(使可调字符串“”))
(do*((I0(+I1))
(x(字符串i)(字符串i)))
(=(+I1)(长度字符串))无)
(如果(eql分隔符x)
(除非(string=”“当前单词)
(推送当前单词)
(推送(字符串分隔符)字)
(设置当前单词(使字符串“”可调)
(矢量推送扩展x当前字)))
(歌词)
但这不会打印出最后一个子字符串/单词。我不知道发生了什么事
提前谢谢你的帮助 问题出现在do*循环的结束条件之后。当变量i到达字符串末尾时,do*循环退出,但仍有一个当前单词尚未添加到单词中。当满足结束条件时,在退出循环之前,需要将x添加到当前单词,然后将当前单词添加到单词:
(defun split-string-with-delimiter (string delimiter)
"Splits a string into a list of strings, with the delimiter still
in the resulting list."
(let ((words nil)
(current-word (make-adjustable-string "")))
(do* ((i 0 (+ i 1))
(x (char string i) (char string i)))
((>= (+ i 1) (length string)) (progn (vector-push-extend x current-word) (push current-word words)))
(if (eql delimiter x)
(unless (string= "" current-word)
(push current-word words)
(push (string delimiter) words)
(setf current-word (make-adjustable-string "")))
(vector-push-extend x current-word)))
(nreverse words)))
但是,请注意,此版本仍然存在错误,因为如果字符串的最后一个字符是分隔符,那么它将包含在最后一个单词中,即(使用分隔符“a.bc.def.”拆分字符串=>(“a”。“bc”。“def”)
我让你加上这张支票
在任何情况下,您都可能希望通过查找分隔符并将当前i和下一个分隔符之间的所有字符同时提取为一个子字符串来提高此操作的效率。类似的内容
- 使用
subseq
- 使用LOOP可以更容易地收集东西
(defun split-string-with-delimiter (string
&key (delimiter #\ )
(keep-delimiters nil)
&aux (l (length string)))
(loop for start = 0 then (1+ pos)
for pos = (position delimiter string :start start)
; no more delimiter found
when (and (null pos) (not (= start l)))
collect (subseq string start)
; while delimiter found
while pos
; some content found
when (> pos start) collect (subseq string start pos)
; optionally keep delimiter
when keep-delimiters collect (string delimiter)))
CL-USER 120 > (split-string-with-delimiter "..1.2.3.4.."
:delimiter #\. :keep-delimiters nil)
("1" "2" "3" "4")
CL-USER 121 > (split-string-with-delimiter "..1.2.3.4.."
:delimiter #\. :keep-delimiters t)
("." "." "1" "." "2" "." "3" "." "4" "." ".")
CL-USER 122 > (split-string-with-delimiter "1.2.3.4"
:delimiter #\. :keep-delimiters nil)
("1" "2" "3" "4")
CL-USER 123 > (split-string-with-delimiter "1.2.3.4"
:delimiter #\. :keep-delimiters t)
("1" "." "2" "." "3" "." "4")
例如:
(defun split-string-with-delimiter (string
&key (delimiter #\ )
(keep-delimiters nil)
&aux (l (length string)))
(loop for start = 0 then (1+ pos)
for pos = (position delimiter string :start start)
; no more delimiter found
when (and (null pos) (not (= start l)))
collect (subseq string start)
; while delimiter found
while pos
; some content found
when (> pos start) collect (subseq string start pos)
; optionally keep delimiter
when keep-delimiters collect (string delimiter)))
CL-USER 120 > (split-string-with-delimiter "..1.2.3.4.."
:delimiter #\. :keep-delimiters nil)
("1" "2" "3" "4")
CL-USER 121 > (split-string-with-delimiter "..1.2.3.4.."
:delimiter #\. :keep-delimiters t)
("." "." "1" "." "2" "." "3" "." "4" "." ".")
CL-USER 122 > (split-string-with-delimiter "1.2.3.4"
:delimiter #\. :keep-delimiters nil)
("1" "2" "3" "4")
CL-USER 123 > (split-string-with-delimiter "1.2.3.4"
:delimiter #\. :keep-delimiters t)
("1" "." "2" "." "3" "." "4")
或修改为使用任何序列(列表、向量、字符串等):
如果您只是在寻找解决方案,而不是练习,则可以使用
cl-ppcre
:
CL-USER> (cl-ppcre:split "(\\.)" "a.bc.def.com" :with-registers-p t)
("a" "." "bc" "." "def" "." "com")
对于要使用多个分隔符拆分并保留它们的情况:
(defun split-string-with-delims (str delims)
(labels ((delim-p (c)
(position c delims))
(tokens (stri test)
(when (> (length stri) 0)
(let ((p (position-if test stri)))
(if p
(if (= p 0)
(cons (subseq stri 0 (1+ p))
(tokens (subseq stri (1+ p) nil) test))
(cons (subseq stri 0 p)
(tokens (subseq stri p nil) test)))
(cons stri nil))))))
(tokens str #'delim-p)))
你可以称之为:
(split-string-with-delims ".,hello world,," '(#\. #\, #\ ))
; => ("." "," "hello" " " "world" "," ",")
或:
关于你的代码,因为有子Q
,我会选择Rainer Joswig的方法(如上),而不是你的生成可调字符串+向量推式扩展