我看过这个问题How to sort a list in Scala by two fields?
这是相似的,但不是重复的。
我可以使用先前问题的答案轻松地对List[DataPoint]
进行排序:
case class DataPoint(keys: List[String], value: Double)
listOfDataPoints.sortBy(point => (point.keys(0), point.keys(1)))
但是我不知道
keys
中的项目数。我知道的是,给定列表中的每个DataPoint
都将具有相同数量的键,因此永远不会对List("a")
和List("a", "b")
进行排序。那么,如何按未知数量的键对列表进行排序?
最佳答案
你想做的是
datapoints.sortby(_.keys)
这显然行不通。当我们看一下sortby的签名时,很明显它为什么不起作用:
sortBy[B](f: (A) ⇒ B)(implicit ord: math.Ordering[B]): List[A]
您的
B
是List[String]
,并且您没有Ordering[List[String]]
的实例。那么我们该怎么办?我们提供一个!为此,我们需要做的是实现方法
def compare(x: T, y: T): Int
我们要比较以下内容:
我们这里的T是字符串,但是我们需要的T可以与此进行比较,因此我们可以更通用一些。
def listOrdering[T](implicit ord: Ordering[T]): Ordering[List[T]] = new Ordering[List[T]] {
def compare(x: List[T], y: List[T]): Int = {
(x, y) match {
case (Nil, Nil) => 0 //both empty => equal
case (Nil, _) => -1 //one of the two empty => empty is the smallest
case (_, Nil) => 1 //one of the two empty => empty is the smallest
case (xhead :: xtail, yhead :: ytail) => {
val headdiff = ord.compare(xhead, yhead)
if (headdiff == 0) compare(xtail, ytail) //recursively compare the tails if equivalent
else (headdiff ) //otherwise, the difference in the heads
}
}
}
}
现在,我们可以显式地为sortby方法提供排序:
datapoints.sortby(_.keys)(listOrdering)
或在隐式范围内提供它们
[1]:您表示这永远不会发生,因此任何选择都足够好