如何编写一个返回与传递给它的集合类型相同的集合类型的 zipWith 方法? [英] How to write a zipWith method that returns the same type of collection as those passed to it?
问题描述
我已经走到这一步了:
implicit def collectionExtras[A](xs: Iterable[A]) = new {
def zipWith[B, C, That](ys: Iterable[B])(f: (A, B) => C)(implicit cbf: CanBuildFrom[Iterable[A], C, That]) = {
val builder = cbf(xs.repr)
val (i, j) = (xs.iterator, ys.iterator)
while(i.hasNext && j.hasNext) {
builder += f(i.next, j.next)
}
builder.result
}
}
// collectionExtras: [A](xs: Iterable[A])java.lang.Object{def zipWith[B,C,That](ys: Iterable[B])(f: (A, B) => C)(implicit cbf: scala.collection.generic.CanBuildFrom[Iterable[A],C,That]): That}
Vector(2, 2, 2).zipWith(Vector(4, 4, 4))(_ * _)
// res3: Iterable[Int] = Vector(8, 8, 8)
现在的问题是上面的方法总是返回一个Iterable
.如何让它返回传递给它的类型集合?(在这种情况下,Vector
)谢谢.
Now the problem is that above method always returns an Iterable
. How do I make it return the collection of type as those passed to it? (in this case, Vector
) Thanks.
推荐答案
你已经足够接近了.只是两行的小改动:
You got close enough. Just a minor change in two lines:
implicit def collectionExtras[A, CC[A] <: IterableLike[A, CC[A]]](xs: CC[A]) = new {
def zipWith[B, C, That](ys: Iterable[B])(f: (A, B) => C)(implicit cbf: CanBuildFrom[CC[A], C, That]) = {
val builder = cbf(xs.repr)
val (i, j) = (xs.iterator, ys.iterator)
while(i.hasNext && j.hasNext) {
builder += f(i.next, j.next)
}
builder.result
}
}
首先需要获取被传递的集合类型,所以我添加了CC[A]
作为类型参数.此外,该集合需要能够复制"自身——这是由 IterableLike
的第二个类型参数保证的——所以 CC[A] <: IterableLike[A, CC[A]]
.请注意,IterableLike
的第二个参数是 Repr
,正是 xs.repr
的类型.
First, you need to get the collection type being passed, so I added CC[A]
as a type parameter. Also, that collection needs to be able to "reproduce" itself -- that is guaranteed by the second type parameter of IterableLike
-- so CC[A] <: IterableLike[A, CC[A]]
. Note that this second parameter of IterableLike
is Repr
, precisely the type of xs.repr
.
自然,CanBuildFrom
需要接收CC[A]
而不是Iterable[A]
.仅此而已.
Naturally, CanBuildFrom
needs to receive CC[A]
instead of Iterable[A]
. And that's all there is to it.
结果:
scala> Vector(2, 2, 2).zipWith(Vector(4, 4, 4))(_ * _)
res0: scala.collection.immutable.Vector[Int] = Vector(8, 8, 8)
这篇关于如何编写一个返回与传递给它的集合类型相同的集合类型的 zipWith 方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!