我有一系列双打矢量:val vectors = Seq[Vector[Double]]
我希望对序列中的所有向量求和,即val total = vectors.sum
例如,如果我有一个包含两个向量[1,2]
和[3,4]
的序列,那么结果应为[4,6]
但是,sum
类型的Vector
方法需要隐式Numeric
。
我现在拥有的是:
val total = vectors.reduce( (one,two) => one.zip(two).map(tuple => tuple._1 + tuple._2) )
我是Scala的新手,但我发现这令人困惑,我认为它可能效率低下。
有更好的方法吗?
答案 0 :(得分:3)
即使向量具有不同的长度并且可以应用于任何数字类型,此尾递归函数也将起作用:
@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()
答案 1 :(得分:1)
您在原始问题中采用的方法与我所做的相同。由于您提出了对效率的关注,我的答案包括使用迭代器,因此像zip
和map
这样的操作将只返回一个新的迭代器,而不是重建整个集合。我还调整了你的方法来处理任何非零数量的输入向量。
示例输入:
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
查找每个'列的总和。在您的'矩阵'。
sumIterator.toList
// List(13, 15, 17, 21, 21)
答案 2 :(得分:0)
使用Vector
减少内部sum
,然后使用Seq
减少外部sum
:
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