Common lisp lisp函数连接字符串列表
我需要编写一个函数,将列表连接成字符串。示例:Common lisp lisp函数连接字符串列表,common-lisp,string-concatenation,Common Lisp,String Concatenation,我需要编写一个函数,将列表连接成字符串。示例: (concatString(引号(“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 concat
(concatString(引号(“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)))
)
)
)
)
当我尝试运行它时,我收到一条“Error:“hello”是非法类型说明符”消息。我已经尝试了很多方法来修改这个函数,但我还没有弄明白。有人有什么想法吗?
连接结果类型和rest
序列
这个应该有用
(concatenate 'string result item)
根据报告:
只需在列表上使用format函数,即可将所有内容转换为字符串,并将它们与正确的格式字符串连接起来
(defun my-concat( list )
(format nil "~{~a~}" list))
如果要将它们与空格连接,请使用带有“~^”指令的此表单:
(defun my-concat( list )
(format nil "~{~a~^ ~}" list))
如果您想过滤掉结果,您可以在格式化列表之前对其进行转换
(defun my-concat(list)
(format nil "~{~a~^ ~}" (remove-if-not #'stringp list)))
串联
需要序列类型说明符作为其第二个参数。要连接两个字符串,应调用concatenate
,如下所示:
(concatenate 'string "hello" "world")
代码中的另一个错误:在将列表的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"
以下对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))))))
为什么把自己限制在清单上
(defun concatenate-strings (sequence)
(reduce #'(lambda (current next)
(if (stringp next)
(concatenate 'string current next)
current))
sequence
:initial-value ""))
要将序列连接到字符串,请使用
concatenate'string
(defun concat-strings (list)
(apply #'concatenate 'string list))
要从列表中删除非字符串的内容,请使用remove if not
(defun concat-strings (list)
(apply #'concatenate 'string
(remove-if-not #'stringp list)))
如果参数不是列表,则会通过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)))
编辑:
正如雷纳所指出的,apply
只适用于长度有限的列表。如果您没有理由相信列表的长度不能超过调用参数限制
减1,则减少
形式更好:
(defun concat-strings (list)
(reduce (lambda (a b)
(concatenate 'string a b))
(remove-if-not #'stringp list)))
这是我的两分钱:
(defmacro concatString(&rest字符串)`(concatenate'字符串)
(@strings))
对不起,我应该提到,如果它忽略列表中不是字符串的项目。因此,如果一个项目是一个数字,则不应将其添加到字符串中。是的,这会改变问题的范围相当大。您可以使用remove if not筛选出非字符串:(defun my concat(list)(格式nil“~{~a}”(remove if not#'stringp list)))我正在检查它是否是字符串,因为对于赋值,如果是数字,则不应将其添加到字符串中。非常感谢您,尽管修复成功了!!!=)这是相对糟糕的:您一直在重复连接创建新的结果字符串。这可能会产生大量的垃圾。@Rainer Joswig我如何修复它?再次访问时,应该注意,如果您想要连接更多的字符串,则使用流(例如,
,将输出转换为字符串)或预先分配结果字符串,然后填充它,效率会更高。
(defun concat-strings (list)
(reduce (lambda (a b)
(concatenate 'string a b))
(remove-if-not #'stringp list)))