MBU*_*MBU 10 common-lisp string-concatenation
我需要编写一个将列表连接成字符串的函数.示例:
(concatString(quote("hello""world")))==>"hello world"
这是我到目前为止:
(defun concatString (list)
"A non-recursive function that concatenates a list of strings."
(cond
((not (listp list))
(princ "Error: argument to concatNR must be a list")(terpri) ())) ; check if parameter is a list
(if (not (null list)) ;check if list is not null
(let ((result (car list)))
(dolist (item (cdr list))
(if (stringp item)
(setq result (concatenate result item)))
)
)
)
)
Run Code Online (Sandbox Code Playgroud)
当我尝试运行它时,我得到一个"错误:"你好"是和非法类型说明符"消息.我已经尝试了很多方法来修改这个功能,但我还没弄清楚.有没有人有任何想法?
Vij*_*hew 16
concatenate需要序列类型说明符作为其第二个参数.要连接两个字符串,您应该调用concatenate:
(concatenate 'string "hello" "world")
Run Code Online (Sandbox Code Playgroud)
代码中的另一个错误:car在分配代码之前,您不确保列表中的字符串是否为字符串result.通过修复代码,我想出了以下实现:
(defun concatString (list)
"A non-recursive function that concatenates a list of strings."
(if (listp list)
(let ((result ""))
(dolist (item list)
(if (stringp item)
(setq result (concatenate 'string result item))))
result)))
;; tests
> (concatString (list "hello" " world"))
"hello world"
> (concatString (list "hello" 1 2 3 " world"))
"hello world"
> (concatString (list "hello" 1 2 "3" " world"))
"hello3 world"
> (concatString (list 1 2 3 "hello" " world"))
"hello world"
Run Code Online (Sandbox Code Playgroud)
以下重新定义concatString更有效,因为它不会创建许多中间字符串对象:
(defun concatString (list)
"A non-recursive function that concatenates a list of strings."
(if (listp list)
(with-output-to-string (s)
(dolist (item list)
(if (stringp item)
(format s "~a" item))))))
Run Code Online (Sandbox Code Playgroud)
zel*_*lio 15
只需在列表中使用format函数,这会将所有内容转换为字符串,并使用正确的格式字符串将它们连接起来.
(defun my-concat( list )
(format nil "~{~a~}" list))
Run Code Online (Sandbox Code Playgroud)
如果要将它们与空格连接,请使用带有"〜^"指令的此表单:
(defun my-concat( list )
(format nil "~{~a~^ ~}" list))
Run Code Online (Sandbox Code Playgroud)
如果您想过滤掉结果,可以在格式化之前转换列表.
(defun my-concat(list)
(format nil "~{~a~^ ~}" (remove-if-not #'stringp list)))
Run Code Online (Sandbox Code Playgroud)
要将序列连接到字符串,请使用concatenate 'string.
(defun concat-strings (list)
(apply #'concatenate 'string list))
Run Code Online (Sandbox Code Playgroud)
要从列表中删除非字符串中的任何内容,请使用remove-if-not.
(defun concat-strings (list)
(apply #'concatenate 'string
(remove-if-not #'stringp list)))
Run Code Online (Sandbox Code Playgroud)
如果参数不是列表,则会发出错误信号remove-if-not.当然,您可以在添加断言之前提供更具体的错误消息,但这并没有真正增加值.
(defun concat-strings (list)
(assert (listp list)
"This is not a list: ~s." list)
(apply #'concatenate 'string
(remove-if-not #'stringp list)))
Run Code Online (Sandbox Code Playgroud)
编辑:
正如Rainer所说,apply只适用于有限长度的列表.如果您没有理由相信您的列表不能超过call-arguments-limit-1,那么reduce表单会更好:
(defun concat-strings (list)
(reduce (lambda (a b)
(concatenate 'string a b))
(remove-if-not #'stringp list)))
Run Code Online (Sandbox Code Playgroud)