使用 set 修改列表的一部分?
使用 set!
我希望能够修改本地状态 list
变量 lst
,但只是其中的一部分
例如,我想在内部列表中插入值:
((1 2) (4 5))
变成
((1 2 3) (4 5))
我希望能够执行类似 set! 的操作! (car lst) (append (car lst) 3)
但这似乎只修改了 (car lst)
生成的临时变量。
我能想到的唯一方法是使用新的所需值创建一个新列表,并将 lst
设置为新列表,但这似乎浪费且不必要。有更好的方法吗?
Using set!
I want to be able to modify a local state list
variable lst
, but only a part of it
For example, I want to insert values inside an inner list:
((1 2) (4 5))
becomes
((1 2 3) (4 5))
I want to be able to do something like set! (car lst) (append (car lst) 3)
But that seems to only modify the temporary variable generated by (car lst)
.
The only way I can think of is to create a new list with the new desired values and set lst
to be the new list, but that seems wasteful and unnecessary. Is there a better way to do it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
试试这个:
当修改 cons/lists 时,你应该使用 set-cdr!和定车!
编辑:对于球拍
使用可变列表:
try this:
when modifying cons/lists you should use set-cdr! and set-car!
EDIT: for racket
use mutable list:
根据您使用的方案解释器,您可能需要做更多的工作。例如,在 Racket 中,列表基元默认情况下不是可变的,您必须使用过程的可变版本:
Depending on which interpreter of Scheme you're using, you might need to do a bit more of work. For instance, in Racket the list primitives are not mutable by default, and you'll have to use the mutable version of the procedures:
在Scheme中创建列表的标准习惯用法是使用
cons
将元素添加到前面,而不是尝试set-cdr!
列表中的最后一个cons单元格。最后,当列表完成后,您可以使用reverse
以正确的顺序获取元素。这样,列表本身就不需要突变。因此,如果您尝试逐步创建列表
(1 2 3)
:()
和cons
开始1 到它。这将为您提供(1)
。cons
2 添加到列表中:(2 1)
cons
3 添加到列表中:(3 2 1)
(1 2 3)
您可能会问为什么这样“更好”。这是因为访问
set-cdr!
的最后一对是一个 O(n) 操作;对于链表,元素不是随机访问的,而是在被访问的元素位置上是线性的。然而,cons
始终为 O(1)。reverse
是一个 O(n) 操作,但只要您仅在最后执行此操作(当您准备好以正确的顺序构建列表时),而不是将其全部调用时间,这不会对性能产生不利影响。The standard idiom in Scheme for creating a list piecemeal is to prepend elements to the front, using
cons
, and not trying toset-cdr!
the last cons cell in the list. At the end, when your list is done, you can then usereverse
to get the elements in the correct order. This way, no list mutation is necessary per se.So if you're trying to create the list
(1 2 3)
piecemeal:()
, andcons
1 to it. This gives you(1)
.cons
2 to the list:(2 1)
cons
3 to the list:(3 2 1)
(1 2 3)
You may ask why this is "better". That's because accessing the last pair to
set-cdr!
is an O(n) operation; with linked lists, elements are not random-access, but are linear on the element position being accessed. Whereas,cons
is always O(1).reverse
is an O(n) operation, but as long as you're doing it only at the end (when you are ready to build the list in the correct order), rather than calling it all the time, that won't detrimentally affect performance.