我需要编写一个 lisp 函数,将 x 添加到列表的第 n 项。例如,(add 5 2 '(3 1 4 6 7))
返回 (3 6 4 6 7)
。
选择nthitem是
(defun nthitem (n list)
(cond ((equal n 1) (car list))
(t (nthitem (-n 1) (cdr list)))))
将 x 添加到列表是:
(defun addto (x list)
(cond ((null list) nil)
(t (cons (+ x (car list))
(addto x (cdr list))))))
但我不能将这两者结合在一起。
最佳答案
我们没有足够地使用 nreconc
。这是一个基于 do
和 reconc
的解决方案。这个想法是沿着列表向下走,以相反的顺序从列表中累积元素,直到到达需要替换的元素的位置。然后你把这些东西粘在一起。也就是说,您反转已累积的列表,并将其附加到由新元素构建的列表和之后的尾部。
(defun add (number index list)
(do ((head '() (list* (first tail) head))
(tail list (rest tail))
(index index (1- index)))
((zerop index)
(nreconc head (list* (+ number (first tail))
(rest tail))))))
CL-USER> (add 5 2 '(3 1 4 6 7))
(3 1 9 6 7)
值得一看的是这些值是如何随时间变化的。让我们考虑一个具有更多数字的示例,并查看每次迭代中 head
、tail
和 index
的值:
CL-USER> (add 90 5 '(0 1 2 3 4 5 6 7 8 9))
(0 1 2 3 4 95 6 7 8 9)
head: ()
tail: (0 1 2 3 4 5 6 7 8 9)
index: 5
head: (0)
tail: (1 2 3 4 5 6 7 8 9)
index: 4
head: (1 0)
tail: (2 3 4 5 6 7 8 9)
index: 3
head: (2 1 0)
tail: (3 4 5 6 7 8 9)
index: 2
head: (3 2 1 0)
tail: (4 5 6 7 8 9)
index: 1
head: (4 3 2 1 0)
tail: (5 6 7 8 9)
index: 0
一旦我们到达 0
,我们可以通过将 number
添加到 (car tail) 来获得最终结果的 rest
并将其与 (cdr tail)
放在一起,即
(list* (+ (car tail) number) (cdr tail)
产生
(95 6 7 8 9)
然后使用 nreconc
取 (4 3 2 1 0)
和 (95 6 7 8 9)
并得到 (0 1 2 3 4 95 6 7 8 9)
,即
(nreconc (list 4 3 2 1 0) '(95 6 7 8 9))
;=> (0 1 2 3 4 95 6 7 8 9)
现在,如果由于某种原因你不能使用do
,例如,这是一个家庭作业,那么跟踪应该仍然给你足够的信息来写一个带有累加器的直接递归版本.不过,无论如何,您仍然需要能够反转
(或nreverse
)列表,并追加
(或nconc
) 一些列表在一起(或者,合并,revappend
或 nreconc
)。
关于function - 将 x 添加到列表的第 n 项的 lisp 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19549728/