Filtering a Scala List by type

Scala

Scala Problem Overview


I have a class structure like this

abstract class A
class B extends A
class C extends A
class D extends A
class E extends A

and I have a collection of the various instances, for example:

val xs = List(new D, new B, new E, new E, new C, new B)

My question is, is there an elegant way to filter out some of the subclasses from the List?

Let's say I want all instances except B's and C's. I can do it with a bunch of isInstanceOf's, or using collect like this:

val ys = (xs collect {
	case b: B => None
	case c: C => None
	case notBorC => notBorC
}).filter(_ != None).asInstanceOf[List[A]]
                               

This works but it feels awkward, mostly because of the filter and cast. Is there a more elegant way? Less code is preferred, and I'd like to have a solution that doesn't need to be updated if I add more subclasses of A.

Scala Solutions


Solution 1 - Scala

collect can be used to filter values on which the function is defined:

Get all values of type A:

xs.collect { case a: A => a }

Get all values except B and C:

xs diff xs.collect { case x@(_: B | _: C) => x }

Solution 2 - Scala

flatMap that shit! (as they say):

scala> val ys = xs flatMap {
     |   case _: B | _: C => None
     |   case other => Some(other)
     | }
ys: List[A] = List(D@7ecdc97b, E@2ce07e6b, E@468bb9d1)

In your case you were getting a List[ScalaObject] because ScalaObject is the least upper bound of None, D, and E.

Solution 3 - Scala

Formulating problems as questions seems to be a pretty good way of solving them :) My question actually provides the answer - just filter by subtype:

val ys = xs filterNot(List(classOf[B], classOf[C]) contains _.getClass)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionhezamuView Question on Stackoverflow
Solution 1 - ScalaGrozzView Answer on Stackoverflow
Solution 2 - ScalaTravis BrownView Answer on Stackoverflow
Solution 3 - ScalahezamuView Answer on Stackoverflow