Moją ulubioną metodą jest skorzystanie z dostarczonej niejawnej kolejności dla krotek, ponieważ jest ona jasna, zwięzła i poprawna:
case class A(tag: String, load: Int) extends Ordered[A] {
// Required as of Scala 2.11 for reasons unknown - the companion to Ordered
// should already be in implicit scope
import scala.math.Ordered.orderingToOrdered
def compare(that: A): Int = (this.tag, this.load) compare (that.tag, that.load)
}
To działa, ponieważ towarzyszOrdered definiuje niejawna konwersja z Ordering[T]celu Ordered[T], który jest w zakresie do dowolnej klasy wykonawczego Ordered. Istnienie niejawnego Orderings dla Tuples umożliwia konwersję z TupleN[...]do Ordered[TupleN[...]]pod warunkiem, że niejawne Ordering[TN]istnieje dla wszystkich elementów T1, ..., TNkrotki, co zawsze powinno mieć miejsce, ponieważ nie ma sensu sortować według typu danych bez Ordering.
Niejawne porządkowanie dla krotek jest Twoim celem dla każdego scenariusza sortowania obejmującego złożony klucz sortowania:
as.sortBy(a => (a.tag, a.load))
Ponieważ ta odpowiedź stała się popularna, chciałbym ją rozwinąć, zauważając, że rozwiązanie podobne do poniższego może w pewnych okolicznościach zostać uznane za klasy korporacyjnej ™:
case class Employee(id: Int, firstName: String, lastName: String)
object Employee {
// Note that because `Ordering[A]` is not contravariant, the declaration
// must be type-parametrized in the event that you want the implicit
// ordering to apply to subclasses of `Employee`.
implicit def orderingByName[A <: Employee]: Ordering[A] =
Ordering.by(e => (e.lastName, e.firstName))
val orderingById: Ordering[Employee] = Ordering.by(e => e.id)
}
Podane es: SeqLike[Employee], es.sorted()posortuje według nazwy i es.sorted(Employee.orderingById)posortuje według identyfikatora. Ma to kilka zalet:
- Sortowania są zdefiniowane w jednym miejscu jako widoczne artefakty kodu. Jest to przydatne, jeśli masz złożone sortowanie na wielu polach.
- Większość funkcji sortowania zaimplementowanych w bibliotece scala działa przy użyciu wystąpień
Ordering, więc podanie kolejności bezpośrednio eliminuje niejawną konwersję w większości przypadków.