Knut Arne Vedaa
Knut Arne Vedaa

Reputation: 15742

Un-optioning an optioned Option

Say I have a val s: Option[Option[String]]. It can thus have the following values:

Some(Some("foo")) Some(None) None

I want to reduce it so that the first becomes Some("foo") while the two others become None. Obviously there are many ways to accomplish this, but I'm looking for a simple, perhaps built-in, less-than-one-liner.

Upvotes: 41

Views: 12236

Answers (6)

Rex Kerr
Rex Kerr

Reputation: 167871

It's a shame that flatten doesn't exist. It should.

Flatten does exist now.

As before,

s getOrElse None

(in addition to the other answers) will also do the same thing.

Upvotes: 38

tgr
tgr

Reputation: 3608

You might use flatMap like the following:

val options = List(Some(Some(1)), Some(None), None)
options map (_ flatMap (a => a))

This will map the List[Option[Option[Int]]] to a List[Option[Int]].
If you just have an Option you can use it as following:

val option = Some(Some(2))
val unzippedOption = option flatMap (b => b)

This will flatten your Option[Option[Int]] to Option[Int].

Upvotes: 1

Dean Hiller
Dean Hiller

Reputation: 20182

I think the conversion to the Iterable is just fine. Use these steps to go from Option[Option[String] to a single Option[String]

s.flatten.headOption 

(which returns Option[String])

Upvotes: 4

Antonin Brettsnajdr
Antonin Brettsnajdr

Reputation: 4143

Well, I actually don't understand how come it could be just None (the third case). If it can really be also just None, then I would vote for Rex Kerr's answer, otherwise just .get would be enough:

scala> Some(Some("foo")).get
res0: Some[java.lang.String] = Some(foo)

scala> Some(None).get
res1: None.type = None

Upvotes: -4

oxbow_lakes
oxbow_lakes

Reputation: 134260

You could use scalaz join to do this, as this is one of the monadic operations:

doubleOpt.join

Here it is in the REPL:

scala> import scalaz._; import Scalaz._
import scalaz._
import Scalaz._

scala> some(some("X")).join
res0: Option[java.lang.String] = Some(X)

scala> some(none[String]).join
res1: Option[String] = None

scala> none[Option[String]].join
res3: Option[String] = None

It's available to anything with a typeclass instance for a Monad.

Upvotes: 16

Dave Griffith
Dave Griffith

Reputation: 20515

s.flatten

followed by a bunch of characters to get me up to the minimum that stackoverflow allows

Upvotes: 14

Related Questions