在通用方法中返回原始集合类型 [英] Returning original collection type in generic method

查看:181
本文介绍了在通用方法中返回原始集合类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们要创建一个像 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



因此我尝试将签名更改为

  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类型参数[Nothing,Nothing ,List [java.lang.String]]
不符合方法multiMinBy的类型参数bounds [A,B,C< ;: Traversable [A]]
pre>

我认为这是因为 C 出现在 / code>已被推断?所以我翻转了参数的顺序,并添加了一个转换:

  def multiMinBy [A,B:Ordering,C& :Traversable [A]](f:A => B)(xs:C)= {
val minVal = f(xs minBy f)
))。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)
}


Say we want to make a function like minBy that returns all elements of equal minimalism in a collection:

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)

So far, so good, except that we have a Traversable back instead of our initial List.

So I tried changing the signature to

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

in the hope I might get a C back rather than a Traversable[A]. However, I don't get anything back:

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]]

I think this is because we have C appearing in the arguments before A has been inferred? So I flipped the order of the arguments, and added a cast:

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]
}

which works, except we have to call it like this:

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

Is there a way to retain the original syntax, while getting the right collection type back?

解决方案

I think Miles Sabin solution is way too complex. Scala's collection already have the necessary machinery to make it work, with a very small change:

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)
}

这篇关于在通用方法中返回原始集合类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆