如何返回具有不同值的列表?

时间:2012-01-01 15:58:34

标签: recursion scheme racket

如果我有以下列表:

(define thelist '(0 1 0 0 7 7 7))

如何编写一个返回新列表的函数,在该列表中替换所请求单元格中的值。

示例:

(set-cell thelist 2 4)

这将返回一个具有相同值的新列表,但在单元格(2)中将有值4而不是1:

(0 4 0 0 7 7 7)

5 个答案:

答案 0 :(得分:5)

HtDP为解决此类问题提供了一种非常具体的方法。对于这个问题,你的工作是写下列表的模板,然后盯着它,直到你可以看到递归调用的参数应该是什么,以及结果是什么。我希望你在列表上解决了一堆热身问题 - 计算列表的长度,计算列表中6的数量等等。

答案 1 :(得分:4)

虽然可以使用列表实现所请求的功能,但解决该问题的自然方法是使用vector,并记住在Scheme索引中从0开始(这就是为什么vector-set!的第二个参数是1,而不是2):

(define thevector (vector 0 1 0 0 7 7 7))
; thevector is #(0 1 0 0 7 7 7)
(vector-set! thevector 1 4)
; thevector is #(0 4 0 0 7 7 7)

现在,如果肯定需要使用列表,那么这样的事情就可以了:

(define (set-cell lst idx val)
  (cond ((null? lst) '())
        ((zero? idx) (cons val (cdr lst)))
        (else (cons (car lst)
                    (set-cell (cdr lst) (sub1 idx) val)))))

你会这样称呼它:

(define thelist '(0 1 0 0 7 7 7))
(set-cell thelist 1 4)
> (0 4 0 0 7 7 7)

同样,我正在使用基于0的索引,这是常规。另请注意,thelist 已修改,而set-cell会返回包含修改的新列表。

答案 2 :(得分:0)

其他人提到了基于0的索引约定。那么我会假设基于0的索引。

考虑到你如何陈述问题,你得到的其他答案是错误的。我会引用你问题中的关键点(我的重点):

  

这将返回一个具有相同值的新列表,但在单元格(2)中将有值4而不是1.

您给出的答案是修改一个列表,而不是返回一个新构建的列表,同时保留原始列表!

这是一个正确的(虽然不是最理想的)解决方案:

(define (set-list index new-value list)
  (if (= index 0)
      (cons new-value (cdr list))
      (cons (car list)
            (set-list (- index 1) new-value (cdr list))))))

我没有在这里进行错误检查(例如,如果某人传入空列表,或者列表中的元素相对于index的元素太少,或者是负索引)。

答案 3 :(得分:0)

这是一种使用从0开始计数的辅助函数的方法。在每次递归时,计数递增,并缩短列表。

如果达到所需的索引,则递归可以停止。如果它在没有命中索引的情况下到达列表的末尾,则返回原始列表。

(define (set-cell ls ind val)

  (define (aux c ls)
    (cond ((null? ls) ls)
          ((= c ind) (cons val (cdr ls)))
          (else (cons (car ls) (aux (+ c 1) (cdr ls))))))

  (aux 0 ls))

答案 4 :(得分:-1)

上面真是太乱了!保持简单:Scheme有列表集!为了这。 例如:

(define ls (list 1 2 3 4 5))
(list-set! ls 0 "new")
(list-set! ls 3 "changed")
(list-ref ls 0)
  => "new"
ls
  => '("new" 2 3 "changed" 5)

但是,您可能希望限制列表上的分配。矢量更快,因为您不需要遍历前面的元素。无论何时在施工前或长度不断变化时都无法指定长度,请使用列表。