将项目添加到列表末尾的"缺点"是什么?

r b*_*r b 14 lisp list append common-lisp

将项目添加到列表末尾的典型方法是什么?

我有一个列表(1 2 3)并想要添加4(其中4是评估结果(+ 2 2))

(setf nlist '(1 2 3))  
(append nlist (+ 2 2))  
Run Code Online (Sandbox Code Playgroud)

这表示append需要一个列表,而不是一个数字.我怎么做到这一点?

dan*_*lei 27

你可以使用附加的,但要注意,如果在一个循环或很长的列表中使用它会导致糟糕的性能.

(append '(1 2 3) (list (+ 2 2)))
Run Code Online (Sandbox Code Playgroud)

如果性能很重要,通常的习惯是通过预先(使用cons),然后反向(或nreverse)来构建列表.

  • 通常,收费和逆转都很好.如果您有许多长列表并且反转成为性能问题,请使用不同的数据结构或手动指向列表末尾的指针.(其他答案中有一些建议.) (2认同)

Vat*_*ine 6

如果"前面的缺点,通过倒转完成"成语不适合你(例如,如果你需要在其构造期间将列表传递给其他功能),那么还有"跟踪结束"特技.然而,通过在它前面进行构建列表,然后在最终使用它之前使用reverse或nreverse完成它可能更简洁.

从本质上讲,这允许您在构建列表时以正确的顺序列出列表,但代价是需要跟踪它.

(defun track-tail (count)
  (let* ((list (cons 0 nil))
     (tail list))
    (loop for n from 1 below count
       do (progn
        (setf (cdr tail) (cons n nil))
        (setf tail (cdr tail))
        (format t "With n == ~d, the list is ~a~%" n list)))
    list))
Run Code Online (Sandbox Code Playgroud)

这给出了以下输出:

CL-USER> (track-tail 5)
With n == 1, the list is (0 1)
With n == 2, the list is (0 1 2)
With n == 3, the list is (0 1 2 3)
With n == 4, the list is (0 1 2 3 4)
(0 1 2 3 4)
Run Code Online (Sandbox Code Playgroud)


Mir*_*lov 6

你没有指定Lisp的类型,所以如果你使用Emacs Lisp和dash列表操作库,它有一个函数-snoc返回一个新的列表,并将元素添加到结尾.这个名字是相反的"缺点".

(-snoc '(1 2) 3) ; (1 2 3)
Run Code Online (Sandbox Code Playgroud)


Tre*_*son 5

您还可以使用它nconc来创建列表,这类似于追加,只是它修改了输入列表的结构。

(nconc nlist (list (+ 2 2)))
Run Code Online (Sandbox Code Playgroud)

  • 在 Common Lisp 中,仅当 nlist 是 consed 列表而不是文字数据时才使用 NCONC。 (6认同)
  • 可能最好不要向初学者建议“NCONC”。 (4认同)
  • @Faré 永远、永远不要做出绝对的陈述。 (4认同)
  • 永远、永远不要使用 NCONC。它的副作用会让你痛不欲生。而且它的复杂性并不比 APPEND 简单。 (3认同)