Il mio metodo preferito personale è quello di utilizzare l'ordinamento implicito fornito per le tuple, poiché è chiaro, conciso e corretto:
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)
}
Questo funziona perché il compagno perOrdered
definisce una conversione implicita da Ordering[T]
a Ordered[T]
che è nell'ambito di qualsiasi implementazione di classe Ordered
. L'esistenza di implicit Ordering
s per Tuple
s consente una conversione da TupleN[...]
a Ordered[TupleN[...]]
purché Ordering[TN]
esista un implicito per tutti gli elementi T1, ..., TN
della tupla, il che dovrebbe sempre essere il caso perché non ha senso ordinare su un tipo di dati con no Ordering
.
L'ordinamento implicito per le tuple è il tuo punto di riferimento per qualsiasi scenario di ordinamento che coinvolga una chiave di ordinamento composta:
as.sortBy(a => (a.tag, a.load))
Poiché questa risposta si è dimostrata popolare, vorrei approfondirla, osservando che una soluzione simile alla seguente potrebbe in alcune circostanze essere considerata di livello aziendale ™:
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)
}
Dato es: SeqLike[Employee]
, es.sorted()
ordinerà per nome e es.sorted(Employee.orderingById)
ordinerà per ID. Questo ha alcuni vantaggi:
- Gli ordinamenti vengono definiti in un'unica posizione come artefatti di codice visibili. Ciò è utile se disponi di ordinamenti complessi su molti campi.
- La maggior parte delle funzionalità di ordinamento implementate nella libreria scala opera utilizzando istanze di
Ordering
, quindi fornire un ordinamento direttamente elimina una conversione implicita nella maggior parte dei casi.