矢量产品使用地图和减少scala

时间:2016-12-15 12:02:19

标签: scala dictionary vector reduce

我正在尝试使用map和reduce函数计算两个向量之间的向量积。

让我们看看Scala的REPL中会发生什么:

首先,我定义了两个长度相同的矢量

scala> val v1 = Array(1,4,5,2)
v1: Array[Int] = Array(1, 4, 5, 2)

scala> val v2 = Array (3,5,1,5)
v2: Array[Int] = Array(3, 5, 1, 5)

现在我使用zip函数

创建一个新的数组vecZip
scala> val vecZip = v1 zip v2
vecZip: Array[(Int, Int)] = Array((1,3), (4,5), (5,1), (2,5))

现在我想应用reduce方法 (为每个元组的产品做)该数组的每个元素。 我想这个:

val vecToSum = vecZip.map(x=>(List(x).reduce(_*_))) 

我想获得一个列表(vecToSum),其中应用reduce方法来计算总结果。但是我收到了这个错误:

scala>  val vecToSum = vecZip.map(x=>(List(x).reduce(_*_)))
<console>:10: error: value * is not a member of (Int, Int)
    val vecToSum = vecZip.map(x=>(List(x).reduce(_*_)))
                                                  ^

3 个答案:

答案 0 :(得分:2)

你只需要调用map并将元组值相互相乘,如下所示:

val vecToSum = vecZip.map(x => x._1 * x._2) 

vecToSum是一个元组列表,因此x(Int, Int)的元组。因此,如果你打电话给List(x).reduce(...),你就会创建一个唯一值为元组的List,所以这并不是你想要的。

答案 1 :(得分:1)

您的代码实际上要做的是创建单个元组元素的列表,然后尝试减少它。它永远不会以这种方式工作,因为没有什么可以减少 - 列表中已经存在单个元素 - 元组。

相反,你需要通过乘以元素来映射你的vecZip数组元素(元组):

vecZip.map { case (x, y) => x * y }

答案 2 :(得分:1)

你不需要在这里减少。减少Array[(Int, Int)]意味着对数组内的所有元组执行一些关联二进制操作。请注意,它可以在前几个元组上执行操作,然后在该元组和第三元组的结果上执行操作,然后在该元组和第四元组等的结果上执行操作。但是,由于关联性,它可以执行操作在第一和第二元组,同时在第三和第四元组,然后在他们的结果等,这是很好的并行化(和诸如Spark的框架严重依赖它))。

例如,您可以对每个元组的所有第一个元素和所有第二个元素求和:

val reduced = vecZip.reduce((pair1, pair2) => (pair1._1 + pair2._1, pair1._2 + pair2._2))

你想要的只是简单地将每个元组映射到其元素的产品中:

val vecToSum = vecZip.map { case (x, y) => x * y }

请注意,我使用了部分函数(请参见那里的case)以便在元组上执行模式匹配;没有部分功能,它看起来像这样:

val vecToSum = vecZip.map(tuple => tuple._1 * tuple._2)