我知道普通聚合在 Scala 中是如何工作的,以及它的折叠用法。尝试了很多来了解下面的代码是如何工作的,但不能。有人可以帮我解释一下它是如何工作的并给我输出 (10,4)
val input=List(1,2,3,4)
val result = input.aggregate((0, 0))(
(acc, value) => (acc._1 + value, acc._2 + 1),
(acc1, acc2) => (acc1._1 + acc2._1, acc1._2 + acc2._2))
最佳答案
Could someone help me in explaining how it works and gives me a output of (10,4)
使用聚合时,您提供三个参数:
- 您从分区中累积元素的初始值,通常是中性元素
给定分区的函数将在其中累积结果
将合并两个分区的函数
因此在您的情况下,分区的初始值是元组 (0, 0)。
然后,您定义的累加器函数会将您正在遍历的当前元素与元组的第一个元素相加,并将元组的第二个元素递增 1。事实上,它将计算分区中元素的总和及其元素数。
combiner 函数组合了两个元组。正如您定义的那样,它将求和并计算 2 个分区的元素数。它不用于您的情况,因为您按顺序遍历管道。您可以调用 List 上的 .par
,以便获得并行实现以查看组合器的运行情况(请注意,它必须是关联函数)。
因此你得到 (10, 4) 因为 1+2+3+4=10 并且列表中有 4 个元素(你做了 4 个加法)。
您可以在累加器函数中添加打印语句(在顺序输入上运行),以查看其行为方式:
Acc: (0,0) - value:1
Acc: (1,1) - value:2
Acc: (3,2) - value:3
Acc: (6,3) - value:4
I knew how a normal aggregate works in scala and its use over fold.
对于顺序输入,aggregate
是一个foldLeft
:
def aggregate[B](z: =>B)(seqop: (B, A) => B, combop: (B, B) => B): B = foldLeft(z)(seqop)
对于并行输入,列表被分成 block ,以便多个线程可以单独工作。累加器函数在每个 block 上运行,使用初始值。当两个线程需要合并它们的结果时,使用 combine 函数:
def aggregate[S](z: =>S)(seqop: (S, T) => S, combop: (S, S) => S): S = {
tasksupport.executeAndWaitResult(new Aggregate(() => z, seqop, combop, splitter))
}
这是fork-join模型的原理,但是它要求你的任务能够很好地并行化。这里就是这种情况,因为一个线程不需要知道另一个线程的结果来完成它的工作。
关于scala - 聚合如何在 Scala 中工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30828056/