2015-03-24 10 views
5

maggior parte delle implementazioni di SQL (questa domanda non ha nulla a che fare con SQL, è solo un esempio) offrono la funzione COALESCE(x1,x2,...,xn) che restituisce x1 se non è NULL, x2 altrimenti solo se x2 non è NULL né e così sopra. Se tutti i valori xi sono NULL, il risultato è NULL.coalescenza opzioni in Scala

Volevo ottenere qualcosa come SQL COALESCE in Scala per i valori OptionNULL sostituito da None. Vi darò alcuni esempi:

> 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 

Così ho implementato come:

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

Funziona bene, ma mi chiedo se esiste già qualcosa di simile funzione implementata come parte della Scala.

+0

Possibilmente un duplicato di: http://stackoverflow.com/questions/3644154/scala-return-on-first-in-list? – DNA

risposta

10

Shorter ancora, si potrebbe usare collectFirst. Questo lo farà in un solo passaggio, con al massimo un attraversamento della collezione.

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 
+0

Ho accettato questo per la sua preoccupazione per l'efficienza, ottimo! –

3

Find prima opzione definita:

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

Mi piace questo! È la forma più breve finora! –

5

ne dite:

values.flatten.headOption 

Questo funziona poiché Option è implicitamente convertibile in Iterable, così flatten funziona più o meno nello stesso modo in cui una lista di liste.

3

Auto risposta:

Il meccanismo nativo (senza implementare una funzione coalesce) è il concatenamento di chiamate a orElse metodo:

> 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 
Problemi correlati