如何将Scala的Option[X]集合转换为X集合

77

我开始探索Scala,其中一个让我感到好奇的事情是Option类型,以及能够消除null相关错误的承诺。

然而,我还没有找到一种方法将一个列表(或其他集合)中的Option[String]转换为String类型的集合(显然过滤掉任何值为None的选项)。

换句话说,我该如何从这里得到结果:

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

...变成了这样:

List[Int] = List(1)

如果对答案有任何影响,我正在使用Scala 2.8。

2个回答

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

9
值得注意的是,这仅起作用是因为从Option[A]到GenTraversableOnce[A]存在一种隐式转换。 - mutantacule
1
@kosii 看起来(至少在Scala 2.11.6中)转换是从Option[A]到Iterable[A]。 - Rag

58

出于教育目的,您可能会喜欢一些替代方案:

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)

使用Scalaz,你可以执行一个稍有不同的操作,称为sequence,它返回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))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接