generics - 在泛型方法中返回原始集合类型

标签 generics scala collections

假设我们想要创建一个像 minBy 这样的函数,它返回集合中同等极简主义的所有元素:

def multiMinBy[A, B: Ordering](xs: Traversable[A])(f: A => B) = {
  val minVal = f(xs minBy f)
  xs filter (f(_) == minVal)
}

scala> multiMinBy(List("zza","zzza","zzb","zzzb"))(_.last)
res33: Traversable[java.lang.String] = List(zza, zzza)

到目前为止,一切都很好,只是我们有一个 Traversable 返回,而不是我们最初的 List

所以我尝试将签名更改为

def multiMinBy[A, B: Ordering, C <: Traversable[A]](xs: C)(f: A => B)

希望我能得到一个 C 而不是 Traversable[A]。但是,我没有得到任何返回:

scala> multiMinBy(List("zza","zzza","zzb","zzzb"))(_.last)

<console>:9: error: inferred type arguments [Nothing,Nothing,List[java.lang.String]] 
do not conform to method multiMinBy's type parameter bounds [A,B,C <: Traversable[A]]

我认为这是因为在推断 A 之前我们在参数中出现了 C?所以我翻转了参数的顺序,并添加了一个强制转换:

def multiMinBy[A, B: Ordering, C <: Traversable[A]](f: A => B)(xs: C) = {
  val minVal = f(xs minBy f)
  (xs filter (f(_) == minVal)).asInstanceOf[C]
}

这是可行的,只不过我们必须这样调用它:

multiMinBy((x: String) => x.last)(List("zza","zzza","zzb","zzzb"))

有没有办法保留原始语法,同时恢复正确的集合类型?

最佳答案

我认为 Miles Sabin 的解决方案太复杂了。 Scala 的集合已经具备了使其工作所需的机制,只需进行很小的更改即可:

import scala.collection.TraversableLike
def multiMinBy[A, B: Ordering, C <: Traversable[A]]
              (xs: C with TraversableLike[A, C])
              (f: A => B): C = {
  val minVal = f(xs minBy f)
  xs filter (f(_) == minVal)
}

关于generics - 在泛型方法中返回原始集合类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8235462/

相关文章:

scala - 定义从项目代码调用方法的sbt任务?

scala - 我在处理这个 Scala 集合时做错了什么?

scala - 在Slick中的一列中查询具有最大值的一行

scala - 如何为 SBT 设置 -Dsbt.override.build.repos=true 全局?

c# - 如何将本地集合与 Linq-to-SQL 一起使用?

java - 如何在 bean 列表中搜索属性?

c - 如何重载C中的函数?

c# - 设计建议 - 如何将这些方法转换为利用 C# 泛型

ios - 类型 'any View' 不能符合泛型协议(protocol)上的 'View'

java - 如何从删除中转换通用类型