Chu*_*ucK 2 scala scala-collections
我正在尝试为一个序列实现一个distinctOn函数,该函数将接受一个函数f并返回一个序列,当f应用于f时,每个项目都有一个不同的结果.例如:
case class Person(name:String, age:Int)
val people = Seq(Person("Al", 20), Person("Bob", 21),
Person("Bob", 24)).distinctOn(_.name)
//people should be:
Seq(Person("Al", 20), Person("Bob", 21))
Run Code Online (Sandbox Code Playgroud)
返回第一个副本(Al)的位置,并保留顺序.我当前的实现包含一个var,而我使用Sets和GroupBy的其他尝试都没有保留顺序.有没有var的更好的方法来实现它?为了记录,我目前的尝试是:
def distinctOn[A](f: T => A):Seq[T]={
var seen = Set[A]()
seq.foldLeft(Seq[T]()) { (res, curr) => {
if(!seen.contains(f(curr))){
seen = seen ++ Set[A](f(curr))
res ++ Seq(curr)
}else{
res
}
}}
}
Run Code Online (Sandbox Code Playgroud)
下面是它保留顺序如适用,也适用于其他的实现Traversable总比Seq秒.它基于其他集合方法中distinct使用的构建器工厂(也称为CanBuildFroms)的实现和使用.
class TraversableOnceExt[A, CC[A] <: TraversableOnce[A]](coll: CC[A]) {
import collection.generic.CanBuildFrom
def distinctBy[B, That](f: A => B)(implicit cbf: CanBuildFrom[CC[A], A, That]): That = {
val b = cbf(coll)
val seen = collection.mutable.HashSet[B]()
for (x <- coll) {
val v = f(x)
if (!seen(v)) {
b += x
seen += v
}
}
b.result
}
}
implicit def commomExtendTraversable[A, C[A] <: TraversableOnce[A]](coll: C[A]): TraversableOnceExt[A, C] =
new TraversableOnceExt[A, C](coll)
Run Code Online (Sandbox Code Playgroud)