Common Lisp:将多个值连接到vector中

时间:2013-02-17 16:48:28

标签: common-lisp

我需要一个将多个值连接成(简单)向量的函数,类似于(concatenate )。但是,与连接不同,它应该能够处理不是向量或序列的参数。

即。它应该像这样工作:

(concat #(1 2) 3) => #(1 2 3)
(concat 1 2 3) => #(1 2 3)
(concat 1 #(2 3 4)) => #(1 2 3 4)
(concat #(1 2) 2 #(3 4 5)) => #(1 2 3 4 5)

我该怎么做?我想我已经忘记了一些让它成为可能的简单lisp结构。

据我所知,连接不能这样做。并且我不太确定如何使用make来创建它(有,@个consturct将list插入到生成的lisp表单中,但是我不太确定如何在这种情况下区分非序列和序列)。

3 个答案:

答案 0 :(得分:4)

其他回复中的reduce方法及时为二次

以下是线性解决方案:

(defun my-concatenate (type &rest args)
  (apply #'concatenate type
         (mapcar (lambda (a) (if (typep a 'sequence) a (list a)))
                 args)))

答案 1 :(得分:2)

由于我们可以计算序列的长度,我们可以分配结果序列,然后将元素复制到其中。

(defun concat (type &rest items)
  (let* ((len (loop for e in items
                    if (typep e 'sequence)
                    sum (length e)
                    else sum 1))
         (seq (make-sequence type len)))
    (loop with pos = 0
          for e in items
          if (typep e 'sequence)
          do (progn
               (setf (subseq seq pos) e)
               (incf pos (length e)))
          else
          do (progn
               (setf (elt seq pos) e)
               (incf pos)))
    seq))


CL-USER 17 > (concat 'string "abc" #\1 "def" #\2)
"abc1def2"

以上适用于矢量。列表的版本留作练习。

答案 2 :(得分:1)

defun my-concatenate (type &rest vectors)
  (reduce (lambda (a b)
            (concatenate
             type 
             (if (typep a 'sequence) a (list a))
             (if (typep b 'sequence) b (list b))))
          vectors))

您可以在#'concatenate上使用reduce对您的参数进行一些修改。如果其中一个参数不是一个序列,只需将其转换为一个列表(连接甚至可以使用简单向量和列表的混合参数)。

CL-USER> (my-concatenate 'list #(1 2 3) 3 #(3 5))
   (1 2 3 3 3 5)

CL-USER> (my-concatenate 'simple-vector #(1 2 3) 3 #(3 5))
   #(1 2 3 3 3 5)

CL-USER> (my-concatenate 'simple-vector 1 #(2 3) (list 4 5))
   #(1 2 3 4 5)

编辑:好吧,你应该接受另一个答案。