Scala 中向量序列的总和

Sum of sequence of Vectors in Scala

我有一个双精度向量序列:val vectors = Seq[Vector[Double]]

我想对序列中的所有向量求和,即 val total = vectors.sum

例如,如果我有一个包含两个向量 [1,2][3,4] 的序列,那么结果应该是 [4,6]

但是,Vector 类型的 sum 方法需要隐式 Numeric.

我现在拥有的是:

val total = vectors.reduce( (one,two) => one.zip(two).map(tuple => tuple._1 + tuple._2) )

我是 Scala 的新手,但我觉得这很混乱,我认为它可能效率低下。

有更好的方法吗?

即使 Vectors 具有不同的长度并且可以应用于任何数字类型,这个尾递归函数仍然有效:

@scala.annotation.tailrec
def recSum[T : Numeric](s : Iterable[Iterable[T]]) : List[T] = {
  val goodVecs = s.filterNot(_.isEmpty)

  if(goodVecs.isEmpty) 
    List.empty[T]
  else 
    goodVecs.map(_.head).sum :: recSum(goodVecs.map(_.tail))
}

将其应用于您的示例:

recSum(Seq(Vector(1.0,2.0), Vector(3.0,4.0,5.0))) //List(4.0,6.0,5.0)

recSum(Seq.empty[Vector[Double]]) // List()

您在原始问题中采用的方法与我采用的方法相同。由于您提出了对效率的担忧,我的回答包括迭代器的使用,因此 zipmap 之类的操作只会 return 一个新的迭代器,而不是重建整个集合。我还调整了您的方法以适用于任何 non-zero 个输入向量。

示例输入:

val vecs = Seq(   
  Vector(1,2,3,4,5),
  Vector(2,3,4,5,6),
  Vector(8,2,6,4,2),
  Vector(2,8,4,8,8) 
)

第一步,将Seq[Vector]转换为Seq[Iterator]

val iterators: Seq[Iterator[Int]] = vecs.map(_.iterator)

现在 reduce 那个 Seq 变成了一个迭代器。这与您在原始问题中所写的非常相似:

val sumIterator = iterators.reduce[Iterator[Int]]{ (itrA, itrB) =>
  // combine 2 of the iterators into a sum of their individual parts
  // the resulting iterator will then be combined with the next iterator
  // so you end up with a single iterator of the total sum for each 'column'

  (itrA zip itrB) map { case (a, b) => a + b }
}

您现在可以使用 sumIterator 计算 'matrix' 中每个 'column' 的总和。

sumIterator.toList
// List(13, 15, 17, 21, 21)

sum减少内部Vectors,然后用sum减少外部Seq:

scala> val vectors: Seq[Vector[Double]] = List(Vector(.1,.2),Vector(.3,.4))
vectors: Seq[Vector[Double]] = List(Vector(0.1, 0.2), Vector(0.3, 0.4))

scala> vectors.map(_.sum).sum
res10 Double = 1.0