Can't use a combination of fold, count and filter

I want to count the total amount of Class2 where Class2.b == 444. In this case, there are 4 of them.

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) }
}

Answers


First error: you can't use point-free notation here:

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) }
                                                           ^

Second error: fold method accepts supertype of elements type as the first parameter:

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

In this case it's Any (common supertype of (Class1, Seq[Class2]) and Int).

You have to use foldLeft:

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

To use fold you have to convert elements of source to Int:

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

Note that you could use sum instead of fold(0){_ + _}, you could also use view to avoid intermediate collection creation:

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

Method fold is not the same as foldLeft. It's a special case of method 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 for parallel collection splits collection into parts (Seq(1), Seq(2), Seq(3), Seq(4)), aggregates each part using operation {(a, e) => println(a -> e); 0}: (0,1), (0,2), (0,3), (0,4) and then aggregates results using the same operation: (0,0) 3 times.

In general (method aggregate) you have to provide different methods to aggregate each part and to combine results from different parts like this:

source.aggregate(0)( (acc, item) => acc + item._2.count(_.b == 444), _ + _ )
// Int = 4

Need Your Help

How can I override a method in Javascript and apply it to the original object, not a child?

javascript html5 html5-audio prototypal-inheritance

I'm trying to override the play() method of the Audio object, but I don't want to do so just for a child object. I want to apply it to the standard Audio object.

Most efficient language to implement tensor factorization for Web Application

python c++ mysql django large-data

I have implemented Tensor Factorization Algorithm in Matlab. But, actually, I need to use it in Web Application.