distinctLastBy
次の方法の優れたパフォーマンスを備えたソリューションを探しています。
import scala.language.higherKinds
implicit final class SeqPimp[A, S[A] <: Seq[A]](val s: S[A]) extends AnyVal {
import scala.collection.generic.CanBuildFrom
import scala.collection.mutable.Builder
private final def build[B](build: Builder[B, S[B]] => Unit)(implicit cbf: CanBuildFrom[S[A], B, S[B]]): S[B] = {
val b = cbf()
build(b)
b.result
}
final def distinctBy[B](f: A => B)(implicit cbf: CanBuildFrom[S[A], A, S[A]]): S[A] = {
build[A] { builder =>
val seen = scala.collection.mutable.Set[B]()
for (a <- s; b = f(a); if !(seen contains b)) {
seen += b
builder += a
}
}
}
final def distinctLastBy[B](f: A => B)(implicit cbf: CanBuildFrom[S[A], A, S[A]]): S[A] = {
// instead of keeping the first occurence of an element the last one will be kept
build[A] { builder => builder ++= s.view.reverse.distinctBy(f).reverse }
}
}
例:
case class Num(integralDigits: Int, fractionalDigits: Int)
val nums = Num(2, 11) :: Num(1, 23) :: Num(1, 45) :: Num(3, 11) :: Num(2, 22) :: Nil
nums distinctLastBy (_.integralDigits) // List(Num(1,45), Num(3,11), Num(2,22))
by
元のリストで(-引数の) 最初に出現した順に並べ替えられた結果要素があると便利です。
List(Num(2,22), Num(1,45), Num(3,11))
何か案は?