scala groupBy class then map the results

2019-09-14 14:10发布

问题:

I have a list of elements, and want to group them by class and then process the results.

trait H 
case class A(x: Int) extends H
case class B(x: Int) extends H
val x = List(A(1),B(2),B(3))
val y = x.groupBy(_.getClass)

y.map(_ match {case (A, alist) => println("found me some As")
               case (B, blist) => println("not As")})

Unfortunately this produces errors like:

<console>:17: error: pattern type is incompatible with expected type;
 found   : A.type
 required: Class[_ <: Product]
Note: if you intended to match against the class, try `case _: A`
       y.map(_ match {case (A, alist) => println("found me some As")

That is, I can't seem to find the proper way to do case matching when the item being matched is a class not just an instance of one.

A partial solution is the following:

val z = y.map(_ match {case (atype, alist) => alist })
z.map(_ match {
  case alist if alist.head.isInstanceOf[A] => alist 
  case blist => List()
})

But it feels like there should be a better way of doing this using the keys to the initial Map returned from groupBy.

回答1:

A in case (A, alist) refers to the companion object of A, which has the type A.type. That's why you're getting that error message. If you want to match against the class meta data, you should refer to classOf[A]. There's also no reason to use match, as you can pattern match with map already.

y.map {
    case (c, alist) if(c == classOf[A]) => println("found me some As")
    case (c, blist) if(c == classOf[B]) => println("not As")
}


标签: scala types