2010-05-24 24 views
25

Korzystanie Scala 2.7.7:Jak spłaszczyć listę opcji za pomocą funkcji wyższego rzędu?

Jeśli mam listę opcji, mogę je spłaszczyć przy użyciu do-zrozumienia:

val listOfOptions = List(None, Some("hi"), None) 
listOfOptions: List[Option[java.lang.String]] = List(None, Some(hi), None) 

scala> for (opt <- listOfOptions; string <- opt) yield string 
res0: List[java.lang.String] = List(hi) 

nie podoba mi się ten styl, a raczej użyć HOF. Ta próba jest zbyt rozwlekły do ​​zaakceptowania:

scala> listOfOptions.flatMap(opt => if (opt.isDefined) Some(opt.get) else None) 
res1: List[java.lang.String] = List(hi) 

Intuicyjnie Liczyłam następujące do pracy, ale nie:

scala> List.flatten(listOfOptions) 
<console>:6: error: type mismatch; 
found : List[Option[java.lang.String]] 
required: List[List[?]] 
     List.flatten(listOfOptions) 

Nawet po Wygląda to powinno działać, ale nie robi „t:

scala> listOfOptions.flatMap(_: Option[String]) 
<console>:6: error: type mismatch; 
found : Option[String] 
required: (Option[java.lang.String]) => Iterable[?] 
     listOfOptions.flatMap(_: Option[String]) 
         ^

najlepszym mogę wymyślić to:

scala> listOfOptions.flatMap(_.toList)   
res2: List[java.lang.String] = List(hi) 

... ale wolałbym nie zamieniać opcji na listę. Wydaje się to niezgrabne.

Każda rada?

Odpowiedz

46

W Scala 2.8, spłaszczyć zadziała:


Welcome to Scala version 2.8.0.RC2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_20). 
Type in expressions to have them evaluated. 
Type :help for more information. 

scala> val listOfOptions = List(None, Some("hi"), None) 
listOfOptions: List[Option[java.lang.String]] = List(None, Some(hi), None) 

scala> listOfOptions flatten 
res0: List[java.lang.String] = List(hi) 

To nie działa w 2.7.7, jednakże:


Welcome to Scala version 2.7.7.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_20). 

scala> val listOfOptions = List(None, Some("hi"), None) 
listOfOptions: List[Option[java.lang.String]] = List(None, Some(hi), None) 

scala> listOfOptions.flatten 
:6: error: no implicit argument matching parameter type (Option[java.lang.String]) => Iterable[Nothing] was found. 
     listOfOptions.flatten 

Biblioteka zbiorów została przeprojektowana i ma o wiele lepsze w 2.8, więc być może warto spróbować użyć najnowszej wersji Scala 2.8 RC i sprawdzić, czy to sprawia, że ​​jest ona łatwiejsza w użyciu.

Jeśli naprawdę nie chcesz użyć metody ToList, myślę, że można także napisać to tak:


scala> listOfOptions.flatMap(o => o) 
res: List[java.lang.String] = List(hi) 
nie

także rzecz piękna może, ale przynajmniej działa w 2.7. 7.

+3

Aha. Dziękuję Ci! Raz natknąłem się na flatMap (o => o), ale szybko o tym zapomniałem. Dlaczego flatMap (_) nie działa tak samo dobrze, to ciekawa rzecz. – Synesso

18

celu uzupełnienia odpowiedź Arjan jest w Scala 2.7.7 można użyć List#flatten, ale trzeba, aby pomóc w inferencer typ:

Welcome to Scala version 2.7.7.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_20). 
Type in expressions to have them evaluated. 
Type :help for more information. 

scala> val listOfOptions = List(None, Some("hi"), None) 
listOfOptions: List[Option[java.lang.String]] = List(None, Some(hi), None) 

scala> listOfOptions.flatten[String]     
res0: List[String] = List(hi) 

scala> val x: List[String] = listOfOptions.flatten 
x: List[String] = List(hi) 
Powiązane problemy