17

可能重复:
将项目添加到列表末尾的“缺点”是什么?

在看了很多关于 lisp 的教程并在谷歌上搜索了很多答案之后,我仍然不知道如何在 LISP 中添加到列表的末尾。

我希望我的函数添加'a到列表的末尾,'(b c d)但我只知道如何将它添加到前面。有人可以帮我正确使用 cons'a在列表末尾添加吗?这是我的代码。提前致谢。

(defun AddRt (a list)
  (cond
    ((null list)
      0)
    (t
      (princ (cons a (cons (car list) (cdr list))))
    )))


(AddRt 'a '(b c d))
4

3 回答 3

19

要么push使用last,要么使用nconc

> (defparameter a (list 1 2 3))
A
> (push 4 (cdr (last a)))
(4)
> a
(1 2 3 4)
> (nconc a (list 5))
(1 2 3 4 5)
> a
(1 2 3 4 5)

请注意,这些是破坏性 运算符,即它们修改作为 的的对象,而a不仅仅是 的绑定a

这就是为什么,顺便说一句,你不应该nconc引用列表上使用,比如(nconc '(1 2 3) '(4 5 6)).

PS。请注意,添加到列表的末尾需要完整 的遍历,因此是一个O(length(list))操作。如果您的列表很长,这可能不是一个好主意,因此人们经常使用 push/nreverse 成语,例如,

(let (range)
  (dotimes (i 10 (nreverse range))
    (push i range)))
==> (0 1 2 3 4 5 6 7 8 9)
于 2012-11-13T22:25:21.587 回答
7

您可以使用递归函数。另外,你应该避免在里面使用princ。

下面的函数endcons与cons做的事情完全一样,除了在末尾添加值。

(defun endcons (a v)
   (if (null v) (cons a nil) (cons (car v) (endcons a (cdr v)))))

(endcons 'a '(b c d))

当然,你也可以使用append

(append '(b c d) '(a))

另请参阅此相关问题:将项目添加到列表末尾的“缺点”是什么?

于 2012-11-13T11:56:27.377 回答
4

一种方法是反转列表。将元素添加到反向列表的开头。然后最后反转整个列表。

方案代码:

(define (add-to-tail l x)
   (reverse (cons x (reverse l)))

但如果这是您经常需要的操作,那么我建议您找到(单链接)列表以外的数据结构。

于 2012-11-13T20:10:17.903 回答