13

这个问题可能很愚蠢,但是我找不到示例,也无法弄清楚。

我想Person按姓氏、名字和中间名的顺序比较两个班级。这是脑死的方法:

def compare(that: Person): Int = {
  val last: Int = lastName.compare(that.lastName)
  if (last != 0) last
  else {
    val first: Int = firstName.compare(that.firstName)
    if (first != 0) first
    else middleName.compare(that.middleName)
}

我知道有一些更聪明的方法可以做到这一点(可能使用Ordering),但我不能指望它。

托德

一旦我意识到如何在 Ordering 中访问正确的东西,我就明白了这一点。

def compare(that: Person): Int = {
  Ordering.Tuple3(Ordering.String, Ordering.String, Ordering.String).compare(
     (lastName, firstName, middleName),
     (that.lastName, that.firstName, that.middleName))
}

我很确定我可以用更少的显式来逃避,但这很有效并且相当紧凑。

4

2 回答 2

22

选项 1:排序依据

使用该sortBy方法,这可能非常简单:

case class Person(first: String, middle: String, last: String)
val personList = List(Person("john", "a", "smith"), Person("steve", "x", "scott"), Person("bill", "w", "smith"))
personList.sortBy{ case Person(f,m,l) => (l,f,m) } 

选项 2:扩展 Ordered[Person]

通过扩展Ordered[Person],该类将知道如何对自己进行排序,因此我们可以免费获得sortedmin和之类的东西max

case class Person(first: String, middle: String, last: String) extends Ordered[Person] {
  def compare(that: Person): Int =
    (last compare that.last) match {
      case 0 => 
        (first compare that.first) match {
          case 0 => middle compare that.middle
          case c => c
        }
      case c => c
    }
}

val personList = List(Person("john", "a", "smith"), Person("steve", "x", "scott"), Person("bill", "w", "smith"))
personList.sorted
personList.min
personList.max

选项 3:隐式排序

如果您使用隐含的Ordering, ,那么您会得到sorted,min等,而不会将该特定顺序绑定到您的原始类。这种解耦可能很方便,也可能很烦人,具体取决于您的具体情况。

case class Person(first: String, middle: String, last: String)

implicit val ord = new Ordering[Person] { 
  def compare(self: Person, that: Person): Int =
    (self.last compare that.last) match {
      case 0 => 
        (self.first compare that.first) match {
          case 0 => self.middle compare that.middle
          case c => c
        }
      case c => c
    }
}

val personList = List(Person("john", "a", "smith"), Person("steve", "x", "scott"), Person("bill", "w", "smith"))
personList.sorted
personList.min
personList.max
于 2012-05-15T14:19:17.720 回答
4

如果您使用的是 scala 2.13+,则可以使用Ordering.byand orElseBy。这是相当明确的。

case class Person(first: String, middle: String, last: String)

implicit val ordering: Ordering[Person] = Ordering.by[Person, String](_.first)
   .orElseBy(_.middle)
   .orElseBy(_.last)

val list = List(Person("john", "a", "smith"), Person("steve", "x", "scott"), Person("bill", "w", "smith"))

list.sorted

于 2020-07-29T14:06:49.800 回答