了解Scala中的聚合

时间:2015-07-30 10:04:05

标签: scala scala-collections scala-2.10

我试图理解Scala中的聚合,并举一个例子,我理解逻辑,但第二个的结果我试图让我困惑。

请告诉我,我哪里出错了。

代码:

val list1 = List("This", "is", "an", "example");

val b = list1.aggregate(1)(_ * _.length(), _ * _)

1 *“This”。length = 4

1 *“is”。length = 2

1 *“an”。length = 2

1 *“example”.length = 7

4 * 2 = 8,2 * 7 = 14

8 * 14 = 112

输出也是112。 但对于下面的内容,

val c = list1.aggregate(1)(_ * _.length(), _ + _)

我以为会是这样的。 4,2,2,7

4 + 2 = 6

2 + 7 = 9

6 + 9 = 15,

但输出仍为112。

理想情况下,我在seqop提到的操作,_ * _.length

请你解释或纠正我哪里出错了。?

1 个答案:

答案 0 :(得分:0)

aggregate应该用于仅计算关联和交换操作。让我们看看函数的签名:

def aggregate[B](z: ⇒ B)(seqop: (B, A) ⇒ B, combop: (B, B) ⇒ B): B

B可以看作是累加器(并且将是您的输出)。你给出一个初始输出值,然后第一个函数是如何向这个累加器添加一个值A,第二个函数是如何合并2个累加器。 Scala"选择"聚合您的集合的方法,但如果您的聚合不是关联和可交换的,则输出不是确定性的,因为订单很重要。看看这个例子:

val l = List(1, 2, 3, 4)
l.aggregate(0)(_ + _, _ * _)

如果我们创建一个累加器,然后汇总我们获得的所有值1 + 2 + 3 + 4 = 10,但如果我们决定通过将列表分成两半来并行化,那么我们就可以(1 + 2) * (3 + 4) = 21

所以现在发生的事情是,List聚合与foldLeft相同,这解释了为什么更改第二个函数并没有改变输出。但aggregate可能有用的地方就是Spark或其他分布式环境,在这些环境中,独立地对每个分区进行折叠可能很有用,然后将结果与第二个函数结合起来。