我个人最喜欢的方法是使用提供的元组隐式排序,因为它清晰、简洁且正确:
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)
}
这是有效的,因为它的同伴Ordered
定义了一个隐式转换Ordering[T]
,Ordered[T]
它在任何实现的类的范围内Ordered
。对于 s的隐式Ordering
s的存在使得从到Tuple
的转换能够为元组的所有元素提供隐式存在,这应该总是如此,因为对没有的数据类型进行排序是没有意义的。TupleN[...]
Ordered[TupleN[...]]
Ordering[TN]
T1, ..., TN
Ordering
Tuples 的隐式排序是任何涉及复合排序键的排序方案的首选:
as.sortBy(a => (a.tag, a.load))
由于这个答案已被证明很受欢迎,我想对其进行扩展,并指出类似于以下的解决方案在某些情况下可能被视为企业级™:
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)
}
Given es: SeqLike[Employee]
,es.sorted()
将按名称排序,es.sorted(Employee.orderingById)
并将按 id 排序。这有几个好处:
- 排序在单个位置定义为可见的代码工件。如果您在许多字段上有复杂的排序,这很有用。
- scala 库中实现的大多数排序功能都使用 的实例进行操作
Ordering
,因此在大多数情况下提供排序直接消除了隐式转换。