gpt4 book ai didi

scala按类型过滤

转载 作者:行者123 更新时间:2023-12-01 09:55:05 25 4
gpt4 key购买 nike

看过TypeTag相关文章,但无法实现按元素类型过滤集合。

例子:

trait A
class B extends A
class C extends A

val v = Vector(new B,new C)
v filter ( _.isInstanceOf[B] )

上面的代码运行良好。但是我想从 v 中提取 filter。例如

def filter[T,T2](data:Traversable[T2]) = (data filter (  _.isInstanceOf[T])).asInstanceOf[Traversable[T]]

//Then filter v by
filter[B,A](v)

在这种情况下,我收到警告抽象类型 T 未选中,因为它已被删除消除。我尝试使用 TypeTag,但在运行时获取 Type 似乎并不容易。

有没有什么优雅的方案来实现filter功能?任何通过 scala 宏的解决方案也是可以接受的。

最佳答案

您需要提供 ClassTag,而不是 TypeTag,并使用模式匹配。 ClassTags 可以很好地用于模式匹配。您甚至可以使用 collect 方法将 filtermap 一起执行:

def filter[T, T2](data: Traversable[T2])(implicit ev: ClassTag[T]) = data collect {
case t: T => t
}

例如:

val data = Seq(new B, new B, new C, new B)
filter[B, A](data) //Traversable[B] with length 3
filter[C, A](data) //Traversable[C] with length 1

这样做的一个问题是它可能无法按预期使用嵌套泛型类型。

collect 方法接受PartialFunction 类型的参数,表示不需要在整个域上定义的函数。当使用 collect 元素时,未定义 PartialFunction 的元素会被过滤掉,并且匹配某些 case 语句的元素会被相应地映射。

您也可以使用existential types并让编译器推断出 data 参数的类型以获得更简洁的语法。您也可以使用context bounds :

def filter[T : ClassTag](data: Traversable[_]) = data collect { case t: T => t }
filter[B](data)

这里的方法的一个问题是您拥有的原生 filter 方法之间存在显着差异:这些方法总是返回 Traversable 而原生 filter 尽可能返回最佳类型。例如:

val data = Vector(new B, new B, new C, new B)
data filter { _.isInstanceOf[B] } //Vector[A]
data filter { _.isInstanceOf[B] } map { _.asInstanceOf[B] } //Vector[B]
data collect { case t: B => t } //Vector[B]. Note that if you know the type at the calling point, this is pretty concise and might not need a helper method at all

//As opposed to:
filter[B](data) //Traversable[B], not a Vector!

您可以使用 CanBuildFrom 来解决此问题使用另一个隐式参数的模式。您也可以使用implicit classes本质上将方法添加到类中(而不是以上面显示的静态样式调用方法)。所有这些加起来是一个相当复杂的方法,但如果您对这些增强功能感兴趣,我将把它留在这里:

implicit class RichTraversable[T2, Repr <: TraversableLike[T2, Repr], That](val trav: TraversableLike[T2, Repr]) extends AnyVal {
def withType[T : ClassTag](implicit bf: CanBuildFrom[Repr, T, That]) = trav.collect {
case t: T => t
}
}

这将允许您这样做:

data.withType[B] //Vector[B], as desired    

关于scala按类型过滤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29886246/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com