聚合如何在scala中工作?

时间:2015-06-14 09:59:50

标签: scala

我知道普通聚合在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))

1 个答案:

答案 0 :(得分:4)

  

有人可以帮助我解释它是如何工作的,并给我一个输出   (10,4)

使用聚合时,您提供三个参数:

  • 从分区累积元素的初始值,通常是中性元素
  • 给定分区的函数会在其中累积结果

  • 将两个分区合并的功能

因此,在您的情况下,分区的初始值是元组(0,0)。

然后,您定义的累加器函数将对您使用元组的第一个元素进行遍历的当前元素求和,并将元组的第二个元素递增1。实际上,它将计算分区中元素的总和及其元素数。

组合器功能组合了两个元组。正如您所定义的那样,它将对总和求和并计算2个分区的元素数。它没有在您的情况下使用,因为您按顺序遍历管道。您可以在List上调用.par,以便获得并行实现以查看合并器的运行情况(请注意它必须是关联函数)。

因此你得到(10,4)因为1 + 2 + 3 + 4 = 10并且列表中有4个元素(你做了4次加法)。

您可以在累加器函数中添加print语句(在顺序输入上运行),以查看它的行为:

Acc: (0,0) - value:1
Acc: (1,1) - value:2
Acc: (3,2) - value:3
Acc: (6,3) - value:4
  

我知道普通聚合在scala中是如何工作的,以及它在折叠中的使用方式。

对于顺序输入,aggregatefoldLeft

def aggregate[B](z: =>B)(seqop: (B, A) => B, combop: (B, B) => B): B = foldLeft(z)(seqop)

对于并行输入,列表将拆分为块,以便多个线程可以单独工作。使用初始值在每个块上运行累加器功能。当两个线程需要合并其结果时,使用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模型的原理,但它要求您的任务可以很好地并行化。这就是这种情况,因为线程不需要知道另一个线程的结果来完成它的工作。