2016-12-15 81 views
2

我想要使用地圖和減少功能來計算兩個向量之間的向量乘積。向量產品使用地圖和減少斯卡拉

讓我們看看Scala中的REPL會發生什麼:

首先我定義2個向量與相同長度的

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) 

現在我創建一個使用新的陣列vecZip zip函數

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),其中應用減少方法計算總成績。不過,我得到這個錯誤:

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(_*_))) 
               ^

回答

2

你只需要調用地圖和繁殖的元組彼此的價值觀,像這樣:

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

vecToSum是一個元組列表,所以x是一個元組(Int, Int)。因此,如果你打電話List(x).reduce(...),你正在創建一個List,唯一的值是元組,所以這不是你想要的。

+0

我得到這個錯誤: 斯卡拉> VAL vecToSum = vecZip.map(X => x_.1 * X_。2) :1:錯誤:')'預期但發現雙字面值。 val vecToSum = vecZip.map(x => x_.1 * x_.2) ^ – Pierfrancesco

+0

你有一個錯字:)它應該是'x._1'而不是'x_.1'。 –

+0

非常感謝! – Pierfrancesco

1

你的代碼實際上試圖做的是創建單個元組元素的列表,然後嘗試減少它。它永遠不會以這種方式工作,因爲沒有什麼可以減少的 - 列表中已經有單個元素 - 一個元組。

相反,你需要通過乘以它們的元素映射你的vecZip數組元素(元組):

vecZip.map { case (x, y) => x * y } 
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)