不能使用折叠,计数和过滤的组合

时间:2014-01-28 08:39:09

标签: scala

我想计算Class2 Class2.b == 444的总金额。在这种情况下,有4个。

object Main extends App {
  class Class1(val a: Int)
  class Class2(val b: Int)

  val source = Seq[(Class1, Seq[Class2])](
    (new Class1(1), Seq(new Class2(12), new Class2(2), new Class2(3), new Class2(4))),
    (new Class1(2), Seq(new Class2(222), new Class2(22), new Class2(33), new Class2(444))),
    (new Class1(3), Seq(new Class2(33), new Class2(444), new Class2(3), new Class2(14))),
    (new Class1(4), Seq(new Class2(44), new Class2(444), new Class2(43), new Class2(444)))
  )

  // acc and item are Any!
  val res = source fold(0) { (acc, item) => acc + item._2.count(_.b == 444) }
}

1 个答案:

答案 0 :(得分:4)

第一个错误:你不能在这里使用无点符号:

val res = source.fold(0){ (acc, item) => acc + item._2.count(_.b == 444) }
<console>:10: error: value _2 is not a member of Any
       val res = source.fold(0){ (acc, item) => acc + item._2.count(_.b == 444) }
                                                           ^

第二个错误:fold方法接受元素类型的超类型作为第一个参数:

def fold[A1 >: A](z: A1)(op: (A1, A1) ⇒ A1): A1 

在这种情况下,它是Any(Class1, Seq[Class2])Int的常见超类型。)

您必须使用foldLeft

val res = source.foldLeft(0){ (acc, item) => acc + item._2.count(_.b == 444) }
//res: Int = 4

要使用fold,您必须将source的元素转换为Int

val res = source.map{ _._2.count(_.b == 444) }.fold(0){_ + _}
// res: Int = 4

请注意,您可以使用sum代替fold(0){_ + _},也可以使用view来避免创建中间集合:

val res = source.view.map{ _._2.count(_.b == 444) }.sum
// res: Int = 4

折叠

方法foldfoldLeft不同。这是方法aggregate的一个特例:

scala> (1 to 4).par.fold(0){ (a, e) => println(a -> e); 0 }
(0,1)
(0,4)
(0,3)
(0,2)
(0,0)
(0,0)
(0,0)

fold用于并行收集将集合拆分为多个部分(Seq(1)Seq(2)Seq(3)Seq(4)),使用操作{{1}聚合每个部分}:{(a, e) => println(a -> e); 0}(0,1)(0,2)(0,3)然后使用相同的操作聚合结果:(0,4) 3次。

一般来说(方法(0,0))你必须提供不同的方法来聚合每个部分并组合来自不同部分的结果,如下所示:

aggregate