How to transform Scala collection of Option[X] to collection of X
ScalaScala CollectionsScala OptionScala Problem Overview
I'm starting to explore Scala, and one of the things I'm intrigued by is the Option
type and the promise of being able to eliminate null
related errors.
However I haven't been able to work out how to transform a list (or other collection) of, say, Option[String]
, to a collection of String
(obviously filtering out any values that are None
).
In other words, how do I get from this:
List[Option[Int]] = List(Some(1))
... to this:
List[Int] = List(1)
I'm using Scala 2.8 if that has any impact on the answer.
Scala Solutions
Solution 1 - Scala
val list1 = List(Some(1), None, Some(2))
val list2 = list1.flatten // will be: List(1,2)
Solution 2 - Scala
For educational purposes, you might like some alternatives:
scala> val list1 = List(Some(1), None, Some(2))
list1: List[Option[Int]] = List(Some(1), None, Some(2))
scala> list1 flatten
res0: List[Int] = List(1, 2)
// Expanded to show the implicit parameter
scala> list1.flatten(Option.option2Iterable)
res1: List[Int] = List(1, 2)
scala> list1 flatMap (x => x)
res2: List[Int] = List(1, 2)
scala> list1 flatMap Option.option2Iterable
res3: List[Int] = List(1, 2)
// collect is a simultaneous map + filter
scala> list1 collect { case Some(x) => x }
res4: List[Int] = List(1, 2)
With Scalaz, you can perform a slightly different operation called sequence
, that returns Option[List[Int]]
.
scala> import scalaz._; import Scalaz._
import scalaz._
import Scalaz._
scala> val list1: List[Option[Int]] = List(Some(1), None, Some(2))
list1: List[Option[Int]] = List(Some(1), None, Some(2))
scala> list1.sequence
res1: Option[List[Int]] = None
scala> val list2: List[Option[Int]] = List(Some(1), Some(2))
list2: List[Option[Int]] = List(Some(1), Some(2))
scala> list2.sequence
res2: Option[List[Int]] = Some(List(1, 2))