Scala:在一次操作中过滤和转换

Dav*_*les 2 collections scala

给定异构序列,我如何只提取某种类型的成员,并以类型安全的方式对这些成员进行操作?

如果我有:

trait Foo
case class Bar(baz: String)
case class Qux(bar: Bar, quux: String) extends Foo
case class Corge(grault: Int) extends Foo
Run Code Online (Sandbox Code Playgroud)

如果我想采取这种混合CorgesQuxes...的序列

val s = Seq[Foo](Corge(1), Qux(Bar("2"), "3"), Qux(Bar("4"), "5"), Corge(6), Qux(Bar("2"), "7"))
Run Code Online (Sandbox Code Playgroud)

......然后拉出来Quxes,分组Bar:

Map(
  Bar(2) -> List(Qux(Bar(2),3), Qux(Bar(2),7)), 
  Bar(4) -> List(Qux(Bar(4),5))
)
Run Code Online (Sandbox Code Playgroud)

我可以做这个:

s filter { f => f.isInstanceOf[Qux] } groupBy { 
    f => f.asInstanceOf[Qux].bar }
Run Code Online (Sandbox Code Playgroud)

或者我可以这样做:

(s.filter({ f => f.isInstanceOf[Qux] }).asInstanceOf[Seq[Qux]]) groupBy { 
    q => q.bar }
Run Code Online (Sandbox Code Playgroud)

但无论哪种方式,我需要两个instanceOf检查,当我看起来我应该能够逃脱一个.或者没有.我缺少一些聪明的模式匹配解决方案吗?

Ran*_*ulz 12

甚至比Daniel Martin的解决方案更好的是使用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)
Run Code Online (Sandbox Code Playgroud)