向量转换中的方案/球拍向量 [英] Scheme / Racket Vector in Vector transformation

查看:35
本文介绍了向量转换中的方案/球拍向量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm having a problem transforming a vector like this:

#(#(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))

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

I wrote a piece of test code but the output is wrong. I went into the debugger and I think I know which line of code cause the problem. I can't seems to find a way to make it work. Any help is greatly appreciated.

(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))

推荐答案

这部分有问题:

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

为什么?因为您在 new-table 的所有位置复制了 完全相同的 向量,因此每当您更新一个值时,它都会同时更改所有值时间.很容易看到这一点:

Why? because you're copying the exact same vector in all off new-table's positions, so whenever you update one value, it'll change all of them at the same time. It's easy to see this:

(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!

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

You have to initialize the vector at the beginning; a fixed version of your code would look like this:

(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 的迭代和理解的好问题,所以你不必担心显式使用递归进行迭代,从而得到更清晰的解决方案:

However, the above solution is hard to understand. Fortunately, this seems like a good problem to use Racket's Iterations and Comprehensions, so you don't have to worry about explicitly using recursion for iteration, leading to a much clearer solution:

(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)

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

Either way, the output is as expected:

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

注意:实际上,这是一个过程式编程风格的解决方案,它就地修改了新的向量,并且具有快速高效的优势(它不会创建更多的向量或列出超出绝对必要的列表),但说实话,这不是解决 Scheme 中问题的常用方法.对于函数式编程风格的解决方案,更符合 Scheme 的精神,请参阅@Ankur 的回答.

Note: As it is, this is a procedural programming-style solution, which modifies the new vectors in-place and has the advantage of being fast and efficient (it doesn't create more vectors or lists beyond the strictly necessary), but truth be told, this is not the usual way to solve problems in Scheme. For a functional programming-style solution, more in the spirit of Scheme, see @Ankur's answer.

这篇关于向量转换中的方案/球拍向量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆