我看过这个问题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]

您的BList[String],并且您没有Ordering[List[String]]的实例。那么我们该怎么办?我们提供一个!

为此,我们需要做的是实现方法
def compare(x: T, y: T): Int

我们要比较以下内容:
  • 如果两个项目的第一个键不同,则使用该键对
  • 进行排序
  • 否则,按列表其余部分排序
  • 如果列表中的一个为空,则另一个列表为第一[1]

  • 我们这里的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]:您表示这永远不会发生,因此任何选择都足够好

    08-24 16:28
    查看更多