25

我有一个事物列表(我称之为 L)、一个索引(N)和一个新事物(NEW)。如果我想用 NEW 替换 L 在 N 的东西,最好的方法是什么?我是否应该将子列表增加到 N 并从 N 到列表末尾,然后使用列表将第一部分 NEW 和最后一部分的新列表粘合在一起?还是有更好的方法来做到这一点?

4

10 回答 10

28
(setf (nth N L) NEW)

应该做的伎俩。

于 2008-10-04T21:01:53.537 回答
8

你打算多久做一次;如果你真的想要一个数组,你应该使用一个数组。否则,是的,创建一个由前 N 个元素、新元素和尾部的副本组成的新列表的函数就可以了。我不知道有什么内置的,但我有一段时间没有用 Lisp 编程了。

这是 Scheme 中的一个解决方案(因为我知道它比 Common Lisp 更好,并且有一个解释器来检查我的工作):

(define (replace-nth list n elem)
  (cond
    ((null? list) ())
    ((eq? n 0) (cons elem (cdr list)))
    (#t (cons (car list) (replace-nth (cdr list) (- n 1) elem)))))
于 2008-10-04T20:28:37.863 回答
7
(setf (nth N L) T)

如果您要做的是“破坏性”修改,即实际更改现有列表,则这是最清晰,最简洁,最快的方法。它不分配任何新内存。

于 2008-10-05T15:07:21.240 回答
4

我只是尝试修复 hazzen 的代码:

(define (replace-nth list n elem)
  (cond 
    ((null? list) ())
    ((eq? n 0) (cons elem list))
    (#t (cons(car list) (replace-nth (cdr list) (- n 1) elem)))))

> (replace-nth (list 3 2 9 2) 2 8)
(3 2 8 9 2)

此代码在列表中插入了新元素。如果我们想替换一个元素:

(define (replace-nth list n elem)
  (cond 
    ((null? list) ())
    ((eq? n 0) (cons elem (cdr list)))
    (#t (cons(car list) (replace-nth (cdr list) (- n 1) elem)))))

> (replace-nth (list 3 2 9 2) 2 8)
(3 2 8 2)

0 <= n <= 长度(列表)- 1

于 2008-10-05T15:30:15.063 回答
3

hazzen 的建议很好(使用数组),因为您可能想做很多这些破坏性的更新,而列表在随机访问时效率很低。最简单的方法

(setq A (make-array 5) :initial-contents '(4 3 0 2 1))
(setf (elt 2 A) 'not-a-number)

其中 A 是一个数组(尽管elt适用于任何序列)。

但是,如果您必须具备功能,那就是

  1. 您想保留旧列表和新列表
  2. 您希望新旧共享尽可能多的内存。

然后你应该使用与 hazzen 代码等效的 Common Lisp:

(defun replace1 (list n elem)
  (cond
    ((null list) ())
    ((= n 0) (cons elem list))
    (t (cons (car list) (replace1 (cdr list) (1- n) elem)))))

这看起来很慢,因为它确实很慢,这可能就是它没有包含在标准中的原因。

hazzen 的代码是 Scheme 版本,有用的是你正在使用的。

于 2008-10-05T02:32:51.340 回答
1

使用 [REPLACE][1] (我使用 X 而不是你的 T 因为 T 是 Lisp 中的真实值):

(replace L (list X) :start1 N)

[1]:http ://www.lispworks.com/documentation/HyperSpec/Body/f_replac.htm替换

于 2008-10-09T04:37:20.947 回答
1

听起来你想要 rplaca 或替换。请参阅http://www.lispworks.com/documentation/HyperSpec/Body/f_rplaca.htmhttp://www.lispworks.com/documentation/HyperSpec/Body/f_replac.htm#replace

于 2008-10-04T20:27:04.950 回答
1

很快你就可以用 JS 在list-replace上做到这一点

于 2012-02-09T10:10:58.183 回答
0

正如其他人所指出的,显而易见的解决方案很慢并且使用内存。如果可能,您应该尝试推迟替换元素,直到您需要对列表执行另一个元素操作,例如(loop for x in list do ...).

这样,您将摊销掉 consing(内存)和迭代(cpu)。

于 2008-10-05T04:42:45.370 回答
-1
(defun replace-nth-from-list  (list n elem)  
      (cond  
        ((null list) ())  
        (t (append (subseq list 0 n) elem (subseq list (+ 1 n)(length list))))))
于 2011-02-08T00:25:42.603 回答