Scala: Filtering based on type

Viewed 6802

I'm learning Scala as it fits my needs well but I am finding it hard to structure code elegantly. I'm in a situation where I have a List x and want to create two Lists: one containing all the elements of SomeClass and one containing all the elements that aren't of SomeClass.

val a = x collect {case y:SomeClass => y}
val b = x filterNot {_.isInstanceOf[SomeClass]}

Right now my code looks like that. However, it's not very efficient as it iterates x twice and the code somehow seems a bit hackish. Is there a better (more elegant) way of doing things?

It can be assumed that SomeClass has no subclasses.

5 Answers

Starting in Scala 2.13, most collections are now provided with a partitionMap method which partitions elements based on a function returning either Right or Left.

That allows us to pattern match a given type (here Person) that we transform as a Right in order to place it in the right List of the resulting partition tuple. And other types can be transformed as Lefts to be partitioned in the left part:

// case class Person(name: String)
// case class Pet(name: String)
val (pets, persons) =
  List(Person("Walt"), Pet("Donald"), Person("Disney")).partitionMap {
    case person: Person => Right(person)
    case pet: Pet       => Left(pet)
  }
// persons: List[Person] = List(Person(Walt), Person(Disney))
// pets: List[Pet] = List(Pet(Donald))
Related