有没有办法在 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)
我是 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)