在 Scala 中对 Ordered.compare 使用模式匹配 [英] Using pattern matching for Ordered.compare in Scala

查看:57
本文介绍了在 Scala 中对 Ordered.compare 使用模式匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下 Scala 类:

I have the following Scala class:

case class Person(firstName: String, lastName: String, age: Int)
    extends Ordered[Person] {
  def compare(that: Person): Int = {
    if (this.lastName < that.lastName) -1
    else if (this.lastName > that.lastName) 1
    else if (this.firstName < that.firstName) -1
    else if (this.firstName > that.firstName) 1
    else this.age compare that.age
  }
}

允许按姓氏、名字和年龄排序.

to allow sorting by lastName, firstName, and age.

我如何使用模式匹配来写这个?我想出了以下方法,但有更好的方法吗?

How can I write this using pattern matching? I've come up with the following, but is there a better way?

case class Person(firstName: String, lastName: String, age: Int)
    extends Ordered[Person] {
  def compare(that: Person): Int = {
    that match {
      case Person(_, thatLastName, _) if this.lastName < thatFile => -1
      case Person(_, thatLastName, _) if this.lastName > thatFile => 1

      case Person(thatFirstName, _, _) if this.firstName < thatFirstName => -1
      case Person(thatFirstName, _, _) if this.firstName > thatFirstName => 1

      case Person(_, _, thatAge) => this.age compare thatAge
    }
  }
}

更新:根据 Landei 的回答,改为使用 Ordering[A]:

UPDATE: Changed to use Ordering[A] as per Landei's answer:

implicit val personOrdering = new Ordering[Person] {
  def compare(first: Person, second:Person): Int = {
    second match {
      case Person(_, thatLastName, _) if first.lastName < thatLastName => -1
      case Person(_, thatLastName, _) if first.lastName > thatLastName => 1

      case Person(thatFirstName, _, _) if first.firstName < thatFirstName => -1
      case Person(thatFirstName, _, _) if first.firstName > thatFirstName => 1

      case Person(_, _, thatAge) => first.age compare thatAge
    }
  }
}

case class Person(firstName: String, lastName: String, age: Int)

但我只匹配second似乎很尴尬.怎样才能让它更优雅"?

but it seems awkward that I only match second. How can I make it more "elegant"?

推荐答案

Scala 中的首选方式是提供隐式 Ordering 而不是 Ordered,后者更加灵活并且不会为继承带来麻烦.

The preferred way in Scala is to provide an implicit Ordering instead of Ordered, which is much more flexible and doesn't give a headache concerning inheritance.

关于模式匹配,我看不到更好的方法,因为比较方法的结果是 Int s,不能保证是 -1, 0, 1.Haskell 的解决方案给enum"对象(LT、EQ、GT)更清晰且模式可匹配,但出于兼容性原因,Scala 似乎在这里遵循了 C++/Java 传统.

Concerning the pattern matching I see no better way, because the result of the compare methods are Ints, which are not guaranteed to be -1, 0, 1. Haskell's solution to give back "enum" objects (LT, EQ, GT) is much cleaner and pattern matchable, but it seems Scala followed the C++/Java tradition here for compatibility reasons.

当然,您可以推出自己的比较框架":

Of course you could roll out your own comparision "framework":

abstract sealed class CompResult(val toInt:Int) {
  def andThen(next: => CompResult): CompResult
}
case object LT extends CompResult(-1) {
 def andThen(next: => CompResult) = LT
}
case object EQ extends CompResult(0) {
  def andThen(next: => CompResult) = next
}
case object GT extends CompResult(1) {
  def andThen(next: => CompResult) = GT
}

implicit def int2Comp(n:Int) =
   if (n == 0) EQ else if (n < 0) LT else GT


(("sdkfhs" compareTo "fldgkjdfl"):CompResult) match {
  case LT => println("less")
  case EQ => println("same")
  case GT => println("more")
}

在你的情况下,你可以写:

In your case you could write:

case class Person(firstName: String, lastName: String, age: Int)
  extends Ordered[Person] {
  def compare(that: Person): Int = {
    (this.lastName compareTo that.lastName).
    andThen (this.firstName compareTo that.firstName).
    andThen (this.age compare that.age).toInt
  }
}

这篇关于在 Scala 中对 Ordered.compare 使用模式匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆