scala - 对两个列表进行元素总和的最快方法
问题描述
我可以使用Zipped函数进行元素运算,如求和。让我有两个列表L1和L2,如下所示
val L1 = List(1,2,3,4)
val L2 = List(5,6,7,8)
我可以通过以下方式对元素进行求和
(L1,L2).zipped.map(_+_)
结果是
List(6, 8, 10, 12)
正如预期的那样。
我在我的实际代码中使用了Zipped函数,但这需要太多时间。实际上,我的列表大小超过1000 个,并且我有超过1000 个列表,我的算法是迭代的,其中迭代可能高达10 亿。
在代码中我必须做以下事情
list =( (L1,L2).zipped.map(_+_).map (_ * math.random) , L3).zipped.map(_+_)
L1、L2和L3的大小相同。此外,我必须在集群上执行我的实际代码。
在Scala中获取列表元素总和的最快方法是什么?
解决方案
一种选择是使用Streaming实现,利用惰性可能会提高性能。
使用LazyList的示例 (在 Scala 中引入2.13
)。
def usingLazyList(l1: LazyList[Double], l2: LazyList[Double], l3: LazyList[Double]): LazyList[Double] =
((l1 zip l2) zip l3).map {
case ((a, b), c) =>
((a + b) * math.random()) + c
}
还有一个使用fs2.Stream的示例 (由fs2
库引入)。
import fs2.Stream
import cats.effect.IO
def usingFs2Stream(s1: Stream[IO, Double], s2: Stream[IO, Double], s3: Stream[IO, Double]): Stream[IO, Double] =
s1.zipWith(s2) {
case (a, b) =>
(a + b) * math.random()
}.zipWith(s3) {
case (acc, c) =>
acc + c
}
但是,如果这些仍然太慢,最好的选择是使用普通数组。
这是一个使用ArraySeq的示例 (在 Scala 中2.13
也引入了),它至少会保持不变性。如果您愿意,可以使用原始数组,但要小心。
(如果你愿意,你也可以使用collections-parallel module
来提高性能)
import scala.collection.immutable.ArraySeq
import scala.collection.parallel.CollectionConverters._
def usingArraySeq(a1: ArraySeq[Double], a2: ArraySeq[Double], a3: ArraySeq[Double]): ArraySeq[Double] = {
val length = a1.length
val arr = Array.ofDim[Double](length)
(0 until length).par.foreach { i =>
arr(i) = ((a1(i) + a2(i)) * math.random()) + a3(i)
}
ArraySeq.unsafeWrapArray(arr)
}
推荐阅读
- python - 获取在函数内部创建的变量值
- sql - SQLite Sum 和 CASE 语句
- composer-php - 如何限制 PHP Deployer 作曲家的内存?
- c# - HRESULT 的异常:Excel Interop v2.0.50727 和 VS2017 上的 0x800A03EC
- angular - 如何检查 Angular 中的占位符内容?
- arrays - 将 char[] 转换为 char*[] 后出现分段错误
- sql - 将两个 select 语句的结果连接在一起
- bash - Bash Jobs:如何输出作业过程信息以及错误?
- c++ - 我如何在 C++ 中调用 talib macd?
- r - 如何分隔包含 JSON 数据的 r data.frame 中的行?