在Scala中对Array of Arrays执行元素添加的惯用方法是什么?

时间:2014-07-23 09:55:07

标签: scala scala-collections

我有一个Array[Array[Float]],保证所有内部数组的长度相同。我想在所有内部数组上执行元素加法。

让我用一个具体的例子来说明这一点。让我们说我的数组包含三个由七个浮点数组成的数组,其中包含以下值:

Array[Array[Float]] = Array(
                          Array(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0), 
                          Array(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0), 
                          Array(0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0)
                      )

现在我想将其转换为大小为7的数组,其中第n个元素是输入Array中第n个元素的总和。对于我的示例输入,输出将是:

Array[Float] = Array(1.0, 3.0, 3.0, 5.0, 5.0, 7.0, 7.0)

要在两个Array[Float]上执行此操作,我知道我可以压缩它们,然后使用地图添加元素。然而,我仍然在努力寻找一种更通用的解决方案,它能够对任何数量的Array[Float]元素进行求和。

任何帮助将不胜感激!

4 个答案:

答案 0 :(得分:8)

scala> a.transpose.map(_.sum)
res1: Array[Double] = Array(1.0, 3.0, 3.0, 5.0, 5.0, 7.0, 7.0)

答案 1 :(得分:2)

另一种方法,

(0 until a(0).size).map (i => a.map(_(i)).sum)
res: Vector(1.0, 3.0, 3.0, 5.0, 5.0, 7.0, 7.0)

一个依赖于并行集合ParSeq的版本,对于(非常)大量的输入行来说可能更有效,

(0 until a(0).size).par.map (i => a.map(_(i)).sum)
res: ParVector(1.0, 3.0, 3.0, 5.0, 5.0, 7.0, 7.0)

答案 2 :(得分:2)

您还可以压缩2个数组并与reduce结合使用。

a.reduce {(x,y) => (x zip y).map{case (xi,yi) => xi + yi}}

答案 3 :(得分:1)

Marth's solution通常最好(更简单,更易读)。但是,如果您的输入数据很大,您可能希望使用transpose的“懒惰”版本:

def transposeIterator[A](a: Seq[Seq[A]]): Iterator[Seq[A]] = {
  val iterators = a.map(_.iterator).view
  if(a.isEmpty) Seq[Seq[A]]().iterator
  else a.head.iterator.map( _ => iterators.map( _.next ) )
}

示例:

val test = (1 to 100).map( _ => (1 to 100000) )

test.transpose.map( _.sum )  // OutOfMem after a long time

transposeIterator(test).map( _.sum ).toVector // ~0.2 sec