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 Ordering
s dla Tuple
s umożliwia konwersję z TupleN[...]
do Ordered[TupleN[...]]
pod warunkiem, że niejawne Ordering[TN]
istnieje dla wszystkich elementów T1, ..., TN
krotki, 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.