我正在尝试使用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函数
创建一个新的数组vecZipscala> 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(_*_)))
^
答案 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)