0

给定一个包含变量类型项的 Scala 集合,我可以按类型进行过滤。

trait X
case class Y(y:Int) extends X
case class Z(z:Int) extends X
val l = List(Y(1), Y(2), Z(3), Z(4))
l.collect{case e: Y=>e} // returns List[Y] = List(Y(1), Y(2))
l.collect{case e: Z=>e} // returns List[Z] = List(Z(3), Z(4))

我需要参数化过滤。

val f = Y
l.collect{case e: f=>e} // should return List[Y] = List(Y(1), Y(2))

最后一行返回error: not found: type fcase该语法中不允许对 Scala 类型进行参数化。

是否有 Scala 式的方法来参数化此过滤操作?(也许使用函数以外的东西collect。)是否需要反射?

4

2 回答 2

1

Inval f = Y Y不是类型,而是伴生对象。

你可以使用这样的类型:

type T = Y
l.collect{case e: T=>e} // returns List[Y] = List(Y(1), Y(2))

或者您可以使用伴随对象,但仅限于某些参数计数:

val t = Y
l.collect{case e @ t(_)=>e} // returns List[Y] = List(Y(1), Y(2))

在这种情况下,您应该使用e @ t(_, _)for case class Y(y1:Int, y2:Int)e @ t(_, _, _)forcase class Y(y1:Int, y2:Int, y3:Int)等。

于 2013-06-03T18:47:44.757 回答
1

您不能将类型本身分配给 val,但可以使用方法类型参数进行参数化:

def filterOnType[T : ClassTag](c: Traversable[Any]): Traversable[T] = {
  val tag = implicitly[ClassTag[T]];
  c.collect { case tag(t) => t } 
}

用于在ClassTag运行时保留有关T. 否则T将被删除,并.collect { case t: T => t }.collect { case t: AnyRef => t }.

scala> filterOnType[Y](l)
res7: Traversable[Y] = List(Y(1), Y(2))

scala> filterOnType[Z](l)
res8: Traversable[Z] = List(Z(3), Z(4))

如果您绝对需要在 val 中保留一些类型的表示,那么保留 aClassTag将在这里工作。必须是隐含的val才能被 拾取filterOnlyType,或者你可以直接给它:filterOnlyType[X](l)(myClassTagForX)

于 2013-06-03T18:48:30.993 回答