在给定一个异构序列的情况下,我如何才能只提取特定类型的成员,并以一种类型安全的方式对这些成员进行操作?
如果我有:
trait Foo
case class Bar(baz: String)
case class Qux(bar: Bar, quux: String) extends Foo
case class Corge(grault: Int) extends Foo如果我想用Corges和Quxes的混合序列.
val s = Seq[Foo](Corge(1), Qux(Bar("2"), "3"), Qux(Bar("4"), "5"), Corge(6), Qux(Bar("2"), "7"))...and只提取按Bar分组的Quxes
Map(
Bar(2) -> List(Qux(Bar(2),3), Qux(Bar(2),7)),
Bar(4) -> List(Qux(Bar(4),5))
)我可以这么做:
s filter { f => f.isInstanceOf[Qux] } groupBy {
f => f.asInstanceOf[Qux].bar }或者我可以这么做:
(s.filter({ f => f.isInstanceOf[Qux] }).asInstanceOf[Seq[Qux]]) groupBy {
q => q.bar }但是,无论哪种方式,我都需要两次instanceOf检查,而我似乎应该能够用一次检查。或者一个都没有。我错过了什么聪明的模式匹配方案吗?
发布于 2014-03-05 22:55:45
比丹尼尔·马丁的解决方案更好的方法是使用collect
val a: Seq[Any] = List(1, 2, "asdf", 4)
a: Seq[Any] = List(1, 2, asdf, 4)
val b = a collect { case s: String => s }
b: Seq[String] = List(asdf)发布于 2014-03-05 22:50:06
不需要显式的instanceOf,只需要在case中使用类的隐式类型。
$ scala
Welcome to Scala version 2.9.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_25).
Type in expressions to have them evaluated.
Type :help for more information.
scala> val a : Seq[Any] = List(1, 2, "asdf", 4)
a: Seq[Any] = List(1, 2, asdf, 4)
scala> val b = a flatMap {i:Any => i match { case s:String => Some(s); case _ => None }}
b: Seq[String] = List(asdf)注意a和b的类型。
https://stackoverflow.com/questions/22210905
复制相似问题