有没有办法在 Scheme 中对两个不同长度的向量求和?

Is there a way of summing two vectors with different lengths in Scheme?

我是 Scheme Lisp 方言的初学者,我正在尝试实现一个函数 sum-vector,它将两个数字向量作为参数,returns 一个向量,其相应元素的总和输入向量。

我试过下面的代码,但我不知道如何对两个不同长度的向量求和。 这是我当前的代码

#lang scheme
(define sum-vector
  (lambda (vec-1 vec-2)
    (let* ((len (vector-length vec-1))
                                       
           (result (make-vector len)))
      (do ((index 0 (+ index 1)))
          ((= index len) result)
        (vector-set! result index
                     (+ (vector-ref vec-1 index)
                        (vector-ref vec-2 index)))))))

(sum-vector (vector 4 6 8 3) (vector 5 6 7))

当我 运行 上面的代码它对具有相同长度的向量完美工作,例如 (sum-vector (vector 4 6 8) (vector 5 6 7)) returns #(9 12 15) 我希望它对不同长度的工作类似,例如(sum-vector (vector 4 6 8 3) (vector 5 6 7)) 应该 return #(9 11 15 3) 但我不知道这样做的逻辑。

一种可能的解决方案是将零附加到每个向量以使其长度相等,然后使用 vector-map:

(define (zero-vector len)
  (make-vector len 0))

(define (append-zeros vec max-len)
  (vector-append vec (zero-vector (- max-len (vector-length vec)))))

(define (sum-vector v1 v2)
  (let ((max-len (max (vector-length v1)
                      (vector-length v2))))
    (vector-map +
                (append-zeros v1 max-len)
                (append-zeros v2 max-len))))

测试:

> (sum-vector (vector 1 2 3) (vector 1 2 3 4 5 6))
'#(2 4 6 4 5 6)
> (sum-vector (vector) (vector 1 2 3 4 5 6 7 8))
'#(1 2 3 4 5 6 7 8)

另一个,Racket-specific方式。

Racket 有一个叫做 comprehensions, which allow for easy iteration over containers. In particular, for/vector returns 结果向量的东西:

> (define v1 (vector 4 6 8 3))
> (define v2 (vector 5 6 7))
> (for/vector ([e1 v1] [e2 v2]) (+ e1 e2))
'#(9 12 15)

请注意,生成的向量是被迭代的最短容器的长度。不过,您可以告诉它生成给定长度的向量:

> (for/vector #:length (vector-length v1) ([e1 v1] [e2 v2]) (+ e1 e2))
'#(9 12 15 0)

它用 0 填充额外的元素。将其与 vector-copy! 结合,它以给定的偏移量将一系列元素从一个向量复制到另一个向量,以将额外的元素从较大的向量复制到较小的(或者如果它们的长度相同则什么都不做),你会得到:

(define (sum-vector v1 v2)
  (let ([sum-helper
         (lambda (short long)
           (let ([result (for/vector #:length (vector-length long)
                                     ([e1 short] [e2 long])
                                     (+ e1 e2))])
             (vector-copy! result (vector-length short)
                           long (vector-length short) (vector-length long))
             result))])
    (if (< (vector-length v1) (vector-length v2))
        (sum-helper v1 v2)
        (sum-helper v2 v1))))

示例:

> (sum-vector (vector 4 6 8 3) (vector 5 6 7))
'#(9 12 15 3)
> (sum-vector (vector 1 2 3) (vector 1 2 3 4 5 6))
'#(2 4 6 4 5 6)
> (sum-vector (vector) (vector 1 2 3 4 5 6 7 8))
'#(1 2 3 4 5 6 7 8)