问题
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