是否有按元素类型过滤和映射集合的内置更优雅的方法?

oxb*_*kes 4 types scala scala-collections

如果我想缩小,例如,Iterable[A]对于特定类型的所有元素(例如String)我可以做:

as filter { _.isInstanceOf[String] }
Run Code Online (Sandbox Code Playgroud)

但是,显然需要使用它作为Iterable[String]可以通过以下方式完成map:

as filter { _.isInstanceOf[String] } map { _.asInstanceOf[String] }
Run Code Online (Sandbox Code Playgroud)

这很难看.当然我可以用flatMap:

as flatMap[String] { a => 
  if (a.isInstanceOf[String]) 
    Some(a.asInstanceOf[String]) 
  else
    None
}
Run Code Online (Sandbox Code Playgroud)

但我不确定这是否更具可读性!我写了一个函数,narrow可以通过implicit转换使用:

as.narrow(classOf[String])
Run Code Online (Sandbox Code Playgroud)

但我想知道是否有一个我忽略的更好的内置机制.特别是因为能够将a缩小List[A]到a List[String]而不是Iterable[String]与我的函数一样,这将是很好的.

Dan*_*ral 8

Scala的语法糖isInstanceOf/ asInstanceOf是模式匹配:

as flatMap { case x: String => Some(x); case _ => None }
Run Code Online (Sandbox Code Playgroud)

因为它使用flatMap,它通常应返回您必须开始的相同集合.

在Scala 2.8上,有一个实验函数可以在对象PartialFunction中定义这种模式.所以,在Scala 2.8上你可以做到:

as flatMap (PartialFunction.condOpt(_ : Any) { case x: String => x })
Run Code Online (Sandbox Code Playgroud)

哪个看起来更大,主要是因为我没有先导入该功能.但是,再一次,在Scala 2.8上有更直接的方法:

as collect { case x: String => x }
Run Code Online (Sandbox Code Playgroud)