在通用方法中返回原始集合类型 [英] Returning original collection type in generic method
问题描述
假设我们要创建一个像 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)
pre>
< console>:9:error:inferred类型参数[Nothing,Nothing ,List [java.lang.String]]
不符合方法multiMinBy的类型参数bounds [A,B,C< ;: Traversable [A]]
我认为这是因为
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 initialList
.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 aTraversable[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 beforeA
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屋!