[英]Scala - Efficient element wise sum of two arrays
我有兩個 arrays,我想將其減少為一個數組,其中每個索引處都有原始 arrays 中兩個元素的總和。 例如:
val arr1: Array[Int] = Array(1, 1, 3, 3, 5)
val arr1: Array[Int] = Array(2, 1, 2, 2, 1)
val arr3: Array[Int] = sum(arr1, arr2)
// This should result in:
// arr3 = Array(3, 2, 5, 5, 6)
我看過這篇文章: Scala 中 arrays 的元素總和,我目前使用這種方法(zip/map)。 但是,將其用於大數據應用程序時,我擔心它的性能。 使用這種方法,必須至少遍歷數組兩次。 在效率方面有更好的方法嗎?
最有效的方法可能是懶惰地做。
與任何面向集合的東西一樣,Scala 2.12 和 2.13 將有所不同(此代碼為 Scala 2.13,但 2.12 將相似......可能會擴展IndexedSeqLike
,但我不確定)
import scala.collection.IndexedSeq
import scala.math.Numeric
case class SumIndexedSeq[+T: Numeric](seq1: IndexedSeq[T], seq2: IndexedSeq[T]) extends IndexedSeq[T] {
override val length: Int = seq1.length.min(seq2.length)
override def apply(i: Int) =
if (i >= length) throw new IndexOutOfBoundsException
else seq1(i) + seq2(i)
}
Array
可以隱式轉換為collection.IndexedSeq
的子類型。 這將計算每次訪問時對應元素的總和(這通常是可取的,因為可以使用可變的IndexedSeq
)。
如果您需要一個Array
,您只需通過一次遍歷即可獲得一個
val arr3: Array[Int] = SumIndexedSeq(arr1, arr2).toArray
但是SumIndexedSeq
可以在任何可以使用Seq
而無需遍歷的地方使用。
作為進一步的優化,特別是如果您確定底層集合/數組不會發生變異,您可以添加一個緩存,這樣您就不會將相同的元素添加到一起兩次。 如果您願意,它也可以推廣到T
上的任何二元運算(在這種情況下,可以刪除Numeric
約束)。
正如 Luis 所說,對於性能問題:實驗和基准測試。 值得記住的是,緩存實現很可能需要將每個元素裝箱以放入緩存中,因此您可能需要多次訪問相同的元素才能使緩存獲勝(並且足夠大的緩存可能具有對分布式系統穩定性的影響)。
好吧,首先,與所有與性能相關的事情一樣,唯一的答案就是進行基准測試。
其次,你確定你需要簡單的可變、不變、奇怪的 Arrays嗎? 你不能使用Vector或ArraySeq 之類的東西嗎?
第三,你可以做這樣的事情或使用一個while
循環,這也是一樣的。
val result = ArraySeq.tabulate(math.min(arr1.length, arr2.length)) { i =>
arr1(i) + arr2(i)
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.