簡體   English   中英

Scala - 兩個 arrays 的有效元素之和

[英]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嗎? 你不能使用VectorArraySeq 之類的東西嗎?

第三,你可以做這樣的事情或使用一個while循環,這也是一樣的。

val result = ArraySeq.tabulate(math.min(arr1.length, arr2.length)) { i =>
  arr1(i) + arr2(i)
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM