按类型过滤 Scala 列表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13381797/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 04:43:29  来源:igfitidea点击:

Filtering a Scala List by type

scala

提问by hezamu

I have a class structure like this

我有这样的班级结构

abstract class A
class B extends A
class C extends A
class D extends A
class E extends A

and I have a collection of the various instances, for example:

我有各种实例的集合,例如:

val xs = List(new D, new B, new E, new E, new C, new B)

My question is, is there an elegant way to filter out some of the subclasses from the List?

我的问题是,是否有一种优雅的方法可以从 List 中过滤掉一些子类?

Let's say I want all instances except B's and C's. I can do it with a bunch of isInstanceOf's, or using collect like this:

假设我想要除 B 和 C 之外的所有实例。我可以用一堆 isInstanceOf 来做到这一点,或者像这样使用 collect:

val ys = (xs collect {
    case b: B => None
    case c: C => None
    case notBorC => notBorC
}).filter(_ != None).asInstanceOf[List[A]]

This works but it feels awkward, mostly because of the filter and cast. Is there a more elegant way? Less code is preferred, and I'd like to have a solution that doesn't need to be updated if I add more subclasses of A.

这有效,但感觉很尴尬,主要是因为过滤器和演员。有没有更优雅的方式?更少的代码是首选,如果我添加更多 A 的子类,我希望有一个不需要更新的解决方案。

回答by Grozz

collectcan be used to filter values on which the function is defined:

collect可用于过滤定义函数的值:

Get all values of type A:

获取类型 A 的所有值:

xs.collect { case a: A => a }

Get all values except B and C:

获取除 B 和 C 之外的所有值:

xs diff xs.collect { case x@(_: B | _: C) => x }

回答by Travis Brown

flatMapthat shit! (as they say):

flatMap那个狗屎!(正如他们所说):

scala> val ys = xs flatMap {
     |   case _: B | _: C => None
     |   case other => Some(other)
     | }
ys: List[A] = List(D@7ecdc97b, E@2ce07e6b, E@468bb9d1)

In your case you were getting a List[ScalaObject]because ScalaObjectis the least upper bound of None, D, and E.

在你的情况你得到一个List[ScalaObject],因为ScalaObject是最上限的NoneDE

回答by hezamu

Formulating problems as questions seems to be a pretty good way of solving them :) My question actually provides the answer - just filter by subtype:

将问题表述为问题似乎是解决问题的一个很好的方法 :) 我的问题实际上提供了答案 - 只需按子类型过滤:

val ys = xs filterNot(List(classOf[B], classOf[C]) contains _.getClass)