List 通过复制重复列表中的元素

List 通过复制重复列表中的元素,list,lisp,common-lisp,repeat,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&g

我需要将列表中的每个元素重复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
这不是我想要的


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

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

  • 有些对象是即时的(例如),不能以任何有意义的方式复制
  • 有些对象是可复制的,复制它们是一种浪费
  • 有些对象是嵌套的,您必须决定是否需要
但是,如果您已经解决了问题并提供了复制功能,那么这并不难:

(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)) 

请注意,
列表
参数的所有元素都被复制,即返回值与参数没有任何关系(在测试中,假设
复制函数
返回一个对象)

使用哪个函数复制带填充指针的可调字符串,这样结果也将是可调字符串?我刚刚用
copy seq
尝试了你的方法,但它会生成固定大小的数组…@Mark:我认为没有函数可以做到这一点,但你可以使用
make array
自己创建一个数组,或者问一个单独的问题。好的,谢谢,现在我知道如何完成我的算法了。它会有点笨重,但现在我知道没有比这更好的了。