list 替换 Common Lisp 列表中的项目?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/170931/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 01:18:13  来源:igfitidea点击:

Replace an item in a list in Common Lisp?

listlispreplacecommon-lisp

提问by Paul Wicks

I have a list of things (I'll call it L), an index(N) and a new thing(NEW). If I want to replace the thing in L at N with NEW, what is the best way to do this? Should I get the sublist up to N and from N to the end of the list and then glue together a new list from the first part, NEW, and the last part using list? Or is there a better way to do this?

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

回答by l0st3d

(setf (nth N L) NEW)

should do the trick.

应该做的伎俩。

回答by hazzen

How often are you going to do this; if you really want an array, you should use an array. Otherwise, yes, a function that makes a new list consisting of a copy of the first N elements, the new element, and the tail will be fine. I don't know of a builtin off the top of my head, but I haven't programmed in Lisp in a while.

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

Here is a solution in Scheme (because I know that better than Common Lisp, and have an interpreter for checking my work):

这是 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)))))

回答by Dan Weinreb

(setf (nth N L) T)

is the clearest, most succinct, and fastest way, if what you want to do is a "destructive" modification, i.e. actually change the existing list. It does not allocate any new memory.

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

回答by user25281

I just try to fix hazzen's code:

我只是尝试修复 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)

This code inserted new element in the list. If we want to replace an element:

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

(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 <= length(list) - 1

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

回答by Nathan Shively-Sanders

hazzen's advice is good (use arrays) since you probably want to do a lot of these destructive updates and lists are very inefficient at random access. The easiest way to do this

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

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

where A is an array (although eltworks for any sequence).

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

However, if you mustbe functional, that is

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

  1. You want to keep around both the old and new lists
  2. You want the old and new to share as much memory as possible.
  1. 您想保留旧列表和新列表
  2. 您希望新旧共享尽可能多的内存。

Then you should use the Common Lisp equivalent of hazzen's code:

然后你应该使用与 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)))))

This looks slow because it is, and that's probably why it's not included in the standard.

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

hazzen's code is the Scheme version, which is useful is that's what you're using.

hazzen 的代码是 Scheme 版本,这很有用,这就是您正在使用的。

回答by David Plumpton

Use [REPLACE][1] (I use X instead of your T as T is the true value in Lisp):

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

(replace L (list X) :start1 N)

[1]: http://www.lispworks.com/documentation/HyperSpec/Body/f_replac.htmREPLACE

[1]:http: //www.lispworks.com/documentation/HyperSpec/Body/f_replac.htmREPLACE

回答by Madil

quickly you can do it with JS on list-replace

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

回答by Mikael Jansson

The obvious solution is slow and uses memory, as noted by others. If possible, you should try to defer replacing the element(s) until you need to perform another element-wise operation on the list, e.g. (loop for x in list do ...).

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

That way, you'll amortize away the consing (memory) and the iteration (cpu).

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

回答by M L

(defun replace-nth-from-list  (list n elem)  
      (cond  
        ((null list) ())  
        (t (append (subseq list 0 n) elem (subseq list (+ 1 n)(length list))))))