简体   繁体   English

Scheme:更改列表中元素的值

[英]Scheme: change value of an element in a list

I hate using SO as a way to find simple functions, but I really can't find a function like this anywhere: 我讨厌使用SO作为查找简单函数的方法,但我真的找不到这样的函数:

Given a list (1 2 3 4 5), I'd like the equivalent of (PHP's, Perl's, Python's) 给出一个列表(1 2 3 4 5),我想要相当于(PHP的,Perl的,Python的)

$a = array(1, 2, 3, 4, 5);   
$a[3] = 100;  

Which results in (1 2 3 100 5) 结果如何(1 2 3 100 5)

Thanks! 谢谢!

You can write list-set! 你可以写list-set! of Guile, like so: Guile,像这样:

(define a (list 1 2 3 4))     ; a is '(1 2 3 4)

(define (list-set! list k val)
    (if (zero? k)
        (set-car! list val)
        (list-set! (cdr list) (- k 1) val)))

(list-set! a 2 100)           ; a is '(1 2 100 4)

(Tried this in DrRacket.) (在DrRacket中试过这个。)

Guile has a built-in function called list-set! Guile有一个名为list-set!的内置函数list-set! that does exactly what you want, using zero-based indices. 这完全符合您的要求,使用从零开始的索引。 For your example, you would have: 对于您的示例,您将拥有:

(define a '(1 2 3 4 5))
(list-set! a 3 100)

I don't think this is standard Scheme, however, and I don't know if it's really efficient. 我不认为这是标准方案,但我不知道它是否真的有效。 For a fixed-length array you should probably use a vector: 对于固定长度的数组,您应该使用向量:

(define a2 #(1 2 3 4 5))
(vector-set! a2 3 100)

I'm pretty sure this is part of the language standard. 我很确定这是语言标准的一部分。

使用没有任何SRFI的标准功能:

(set-car! (list-tail lst k) val)

I may be a bit late, but I have a different answer. 我可能有点晚了,但我有一个不同的答案。

Part of the functional-program paradigm seems to be to try to avoid modifying data when possible. 功能程序范例的一部分似乎是尽可能避免修改数据。 For efficiency reasons you may want to go with the other answers here. 出于效率原因,您可能希望在此处使用其他答案。 But otherwise, consider a non-mutating function such as this: 但除此之外,请考虑一个非变异函数,例如:

(define (list-with lst idx val)
  (if (null? lst)
    lst
    (cons
      (if (zero? idx)
        val
        (car lst))
      (list-with (cdr lst) (- idx 1) val))))

Which passes the following tests: 通过以下测试:

(describe "a function that returns a list with a 'changed' value"
  (it "can modify the edges of lists without having 1-off errors"
    (expect (list-with '(1 2 3 4 5) 0 99) (be equal? '(99 2 3 4 5)))
    (expect (list-with '(1 2 3 4 5) 4 99) (be equal? '(1 2 3 4 99))))
  (it "has something to do with creating new lists"
    (expect (list-with '(1 2 3 4 5) 2 99) (be equal? '(1 2 99 4 5))))
  (it "doesnt just modify the contents of the original list"
    (let ((a '(1 2 3 4 5)))
      (list-with a 2 99)
      (expect a (be equal? '(1 2 3 4 5))))))

(The code is written in Chicken Scheme and the tests with the "missbehave" library. But it seems like pretty portable Scheme.) (代码用Chicken Scheme编写,测试用“missbehave”库。但它似乎是非常便携的Scheme。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM