lisp函数用于连接字符串列表

时间:2011-03-28 09:58:03

标签: common-lisp string-concatenation

我需要编写一个将列表连接成字符串的函数。例如:

    (concatString(quote(“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)))          
        )
      )
  )
)

当我尝试运行它时,我收到“错误:”hello“is and illegal type specifier”消息。我已经尝试了很多方法来修改这个功能,但我还没弄清楚。有没有人有任何想法?

7 个答案:

答案 0 :(得分:16)

只需在列表中使用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)))

答案 1 :(得分:16)

concatenate需要序列类型说明符作为其第二个参数。要连接两个字符串,您应该将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))))))

答案 2 :(得分:7)

要将序列连接到字符串,请使用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)))

编辑:

正如Rainer所说,apply仅适用于有限长度的列表。如果您没有理由相信您的列表不能超过call-arguments-limit减去1,那么reduce表单会更好:

(defun concat-strings (list)
  (reduce (lambda (a b)
            (concatenate 'string a b))
          (remove-if-not #'stringp list)))

答案 3 :(得分:3)

Common Lisp the Language, 2nd Edition

  

连接结果类型& rest   序列

这个应该有效

(concatenate 'string result item)

答案 4 :(得分:3)

根据Common Lisp Cookbook

(concatenate 'string "Karl" " " "Marx")
"Karl Marx"

答案 5 :(得分:2)

为什么要限制自己的名单?

(defun concatenate-strings (sequence)
  (reduce #'(lambda (current next)
              (if (stringp next)
                (concatenate 'string current next)
                current))
          sequence
          :initial-value ""))

答案 6 :(得分:2)

这是我的两分钱:

  

(defmacro concatString(& rest strings)`(concatenate' string   ,@ strings))