Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
按多个字段排序的Scala_Scala - Fatal编程技术网

按多个字段排序的Scala

按多个字段排序的Scala,scala,Scala,这个问题可能很愚蠢,但我找不到一个例子,也弄不明白 我想按姓氏、名和中间名的顺序比较两个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

这个问题可能很愚蠢,但我找不到一个例子,也弄不明白

我想按姓氏、名和中间名的顺序比较两个
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)
}
我知道有一些更聪明的方法可以做到这一点(可能是使用
订购
),但我无法确定

托德

当我意识到如何按顺序访问正确的东西时,我就明白了这一点

def compare(that: Person): Int = {
  Ordering.Tuple3(Ordering.String, Ordering.String, Ordering.String).compare(
     (lastName, firstName, middleName),
     (that.lastName, that.firstName, that.middleName))
}
我很确定我可以用更少的显式词,但这很有效,而且相当紧凑。

选项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]
,类将知道如何对自身进行排序,因此我们可以免费获得
排序
min
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:隐式排序 如果您使用隐式的
排序
,那么您将得到
排序
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

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

案例类人物(第一个:字符串,中间:字符串,最后一个:字符串)
隐式val排序:排序[Person]=按[Person,String]排序(u.first)
.Orelsby(中间)
.Orelsby(u.last)
val list=列表(人物(“约翰”、“a”、“史密斯”)、人物(“史蒂夫”、“x”、“斯科特”)、人物(“比尔”、“w”、“史密斯”))
list.sorted

一旦我发现
StringOrdering
是一种特性,而不是一个目标,我就知道怎么做了。参见上文。this:personList.sortBy{case Person(f,m,l)=>(l,f,m)}看起来有点像魔术。如果您想使用元组技巧反转其中一个字段(即字符串)的顺序,该怎么办?有可能吗?这很不错,但只在2.13开时才有。