1

我在转换这样的向量时遇到问题:

#(#(1 2 3)#(1 2 3)#(1 2 3)#(1 2 3)#(1 2 3)))

变成这样的:

#(#(1 1 1 1 1) #(2 2 2 2 2) #(3 3 3 3 3))

我写了一段测试代码,但输出错误。我进入调试器,我想我知道是哪一行代码导致了问题。我似乎找不到让它工作的方法。任何帮助是极大的赞赏。

(define (test)
  (let* ((table #(#(1 2 3)#(1 2 3)#(1 2 3)#(1 2 3)#(1 2 3)))
         (counter 5)
         (size 3)
         (new-table (make-vector size (make-vector counter #f))))

    (let loop ((sc 0)
               (cc 0))
      (when (not (= cc counter))
        (if (not (= sc size))
            (begin (vector-set! (vector-ref new-table sc) cc (vector-ref (vector-ref table cc) sc))
                   (loop (+ 1 sc) cc))
            (loop 0 (+ 1 cc)))))
    (display new-table))) 

> (test)
#(#(3 3 3 3 3) #(3 3 3 3 3) #(3 3 3 3 3))
4

2 回答 2

4

这部分有一个问题:

(make-vector size (make-vector counter #f))

为什么?因为您在所有 off 的位置复制完全相同的向量new-table,所以每当您更新一个值时,它会同时更改所有这些值。很容易看出这一点:

(define new-table (make-vector 3 (make-vector 3 #f)))
(vector-set! (vector-ref new-table 0) 0 42) ; we modify a single position ...
new-table
=> '#(#(42 #f #f) #(42 #f #f) #(42 #f #f))  ; ... but all of them changed!

您必须在开始时初始化向量;您的代码的固定版本如下所示:

(let* ((table '#(#(1 2 3) #(1 2 3) #(1 2 3) #(1 2 3) #(1 2 3)))
       (counter (vector-length table))
       (size (vector-length (vector-ref table 0)))
       (new-table (make-vector size)))
  ; initialization
  (let loop ((i 0))
    (when (< i size)
      (vector-set! new-table i (make-vector counter))
      (loop (+ i 1))))  
  (let loop ((sc 0)
             (cc 0))
    (when (not (= cc counter))
      (if (not (= sc size))
          (begin
            (vector-set! (vector-ref new-table sc) cc
                         (vector-ref (vector-ref table cc) sc))
            (loop (+ 1 sc) cc))
          (loop 0 (+ 1 cc))))
    new-table))

但是,上面的解决方案很难理解。幸运的是,使用 Racket 的Iterations 和 Comprehensions似乎是一个很好的问题,因此您不必担心显式使用递归进行迭代,从而获得更清晰的解决方案:

(let* ((table '#(#(1 2 3) #(1 2 3) #(1 2 3) #(1 2 3) #(1 2 3)))
       (counter (vector-length table))
       (size (vector-length (vector-ref table 0)))
       (new-table (make-vector size)))
  (for ([sc (in-range size)])
    (vector-set! new-table sc (make-vector counter)) ; initialization
    (for ([cc (in-range counter)])
      (vector-set! (vector-ref new-table sc) cc
                   (vector-ref (vector-ref table cc) sc))))
  new-table)

无论哪种方式,输出都符合预期:

=> '#(#(1 1 1 1 1) #(2 2 2 2 2) #(3 3 3 3 3))

注意:事实上,这是一种程序化编程风格的解决方案,它就地修改新向量,并具有快速高效的优点(它不会创建超出严格必要的更多向量或列表),但事实是被告知,这不是在 Scheme 中解决问题的常用方法。对于更符合 Scheme 精神的函数式编程风格的解决方案,请参阅@Ankur 的回答。

于 2013-05-20T02:45:33.263 回答
4

您还可以使用vector-map来获得所需的输出:

(define table #(#(1 2 3) #(1 2 3) #(1 2 3) #(1 2 3) #(1 2 3)))

(apply vector-map vector (vector->list table))
于 2013-05-20T04:37:22.203 回答