Coalescing options in Scala

情到浓时终转凉″ 提交于 2019-12-09 02:43:43

问题


Most SQL implementations (this question has nothing to do with SQL, it is just an example) offer the function COALESCE(x1,x2,...,xn) which returns x1 if it is not NULL, x2 otherwise only if x2 is not NULL neither and so on. If all xi values are NULL then the result is NULL.

I wanted to get something like SQL's COALESCE in Scala for Option values being NULL replaced by None. I'll give you some examples:

> coalesce(None,Some(3),Some(4))
res0: Some(3)

> coalesce(Some(1),None,Some(3),Some(4))
res1: Some(1)

> coalesce(None,None)
res2: None

So I implemented it as:

def coalesce[T](values: Option[T]*): Option[T] = 
    (List[T]() /: values)((prev: List[T], cur: Option[T]) =>
                          prev:::cur.toList).headOption

It works fine but I wonder if already exists something like this function implemented as part of Scala.


回答1:


Shorter still, you could use collectFirst. This will do it in one step, with at most one traversal of the collection.

def coalesce[A](values: Option[A]*): Option[A] =
    values collectFirst { case Some(a) => a }


scala> coalesce(Some(1),None,Some(3),Some(4))
res15: Option[Int] = Some(1)

scala> coalesce(None,None)
res16: Option[Nothing] = None



回答2:


How about:

values.flatten.headOption

This works since Option is implicitly convertible to Iterable, so flatten works much in the same way as a list of lists.




回答3:


Auto answer:

The native mechanism (without implementing a coalesce function) is the chaining of calls to orElse method:

> None.orElse(Some(3)).orElse(Some(4))
res0: Option[Int] = Some(3)

> Some(1).orElse(None).orElse(Some(3)).orElse(Some(4))
res1: Option[Int] = Some(1)

> None.orElse(None)
res2: Option[Nothing] = None



回答4:


Find first defined option:

def coalesce[T](values: Option[T]*): Option[T] =
  values.find(_.isDefined).flatten


来源:https://stackoverflow.com/questions/29234056/coalescing-options-in-scala

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!