重复列表的元素与复制

时间:2014-07-23 13:19:20

标签: list lisp common-lisp repeat

我需要重复列表中的每个元素N次,即执行这种转换:

(1 2 3) => (1 1 1 2 2 2 3 3 3) ; N = 3

保持元素的顺序很重要,即第一个元素应重复N次,然后重复第二次,等等。

这是我迄今为止的最佳尝试:

(defun my-fnc (lst &optional (n 2))
  (mapcan (lambda (x) (make-list n :initial-element x))
          lst))

看起来很有效:

CL-USER> (defparameter *foo* '("foo" "bar"))
*FOO*
CL-USER> (setf *foo* (my-fnc *foo* 3))
("foo" "foo" "foo" "bar" "bar" "bar")

......但不完全。问题是前三个元素是对同一个对象的引用。

("foo" "foo" "foo" "bar" "bar" "bar")
;{---------------} {---------------}
; the same string   the same string

这不是我想要的。

所以我的问题是:如何以大多数惯用的方式解决问题,以便结果列表的每个元素都可以引用复制的单独对象。

1 个答案:

答案 0 :(得分:7)

这通常是不可能的,因为Common Lisp不提供通用的复制功能。而且,

  • 某些对象是即时的(例如,fixnum),无法以任何有意义的意义复制
  • 某些对象是immutable并且复制它们是一种浪费
  • 某些对象是嵌套的,您必须决定是否需要deep or shallow copy

但是,如果你已经解决了问题并提供了复制功能,那就不太难了:

(defun my-fnc (list &key (repeat 2) copy-function)
  (mapcan (if copy-function
              (lambda (x) 
                (loop :repeat repeat :collect (funcall copy-function x)))
              (lambda (x) (make-list n :initial-element x)))
          list)) 

请注意, all 复制list参数的元素,即返回值没有带intersection的参数(在eq测试下)并假设copy-function返回fresh个对象)