2011-01-19 21 views
68

Zaczynam odkrywać Scalę i jedną z rzeczy, które mnie intrygują jest typ Option i obietnica możliwości usunięcia błędów związanych z null .Jak przekształcić kolekcję Scala opcji [X] na kolekcję X

Jednak nie byłem w stanie wymyślić, jak przekształcić listę (lub inną kolekcję) z, powiedzmy, Option[String], w kolekcję String (oczywiście odfiltrowując wszelkie wartości, które są None).

Innymi słowy, jak mogę z tego:

List[Option[Int]] = List(Some(1)) 

... do tego:

List[Int] = List(1) 

Używam Scala 2.8, czy to ma jakiś wpływ na odpowiedź.

Odpowiedz

120
val list1 = List(Some(1), None, Some(2)) 
val list2 = list1.flatten // will be: List(1,2) 
+2

Żenująco proste (jak miałem nadzieję, że będzie)! Dzięki. – npad

+7

Warto jednak zauważyć, że działa tylko dlatego, że istnieje niejawna zamiana z Opcja [A] na GenTraversableOnce [A] – kosii

+0

@kosii Wygląda (przynajmniej w Scali 2.11.6) konwersja z opcji [A] do Iterable [A] –

53

Dla celów edukacyjnych, może ci się kilka alternatyw:

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) 

Z Scalaz można wykonać nieco inną operację zwaną sequence, która zwraca 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))