Reputation: 5046
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.
Upvotes: 77
Views: 27822
Reputation: 55028
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))
Upvotes: 58
Reputation: 5919
val list1 = List(Some(1), None, Some(2))
val list2 = list1.flatten // will be: List(1,2)
Upvotes: 139