I’m trying to implement a distinctOn function for a sequence which will take a function f and return a sequence for which each item has a distinct result when the f is applied to it. EG:
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))
where the first duplicate (Al) is returned, and order is preserved. My current implementation contains a var, and my other attempts using Sets and GroupBy didn’t preserve order. Is there a better way to implement this without the var? For the record my current attempt is:
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
}
}}
}
Here’s an implementation which preserves order where applicable and also works for other
Traversables thanSeqs. It is based on the implementation ofdistinctand uses the builder factories (a.k.a.CanBuildFroms) used in other collection methods.