在Scala模式匹配系统中使用比较运算符


148

是否可以使用Scala中的模式匹配系统进行比较匹配?例如:

a match {
    case 10 => println("ten")
    case _ > 10 => println("greater than ten")
    case _ => println("less than ten")
}

第二种情况陈述是非法的,但我希望能够指定“当a大于时”。


1
这也可以用于检查函数的计算结果是否为true,例如case x if x.size > 2 => ...
tstenner 2010年

2
要了解的重要一点是,=>运算符左侧的“模式”确实是“模式”。第一种情况下的表达式中的10不是整数文字。因此,您无法在左侧执行操作(例如>检查或说函数应用程序isOdd(_))。
Ustaman Sangat

Answers:


292

您可以if在模式之后添加一个保护,即一个和布尔表达式:

a match {
    case 10 => println("ten")
    case x if x > 10 => println("greater than ten")
    case _ => println("less than ten")
}

编辑:请注意,这是比肤浅到把一个不同if 之后=>,因为一个模式不会如果保护是不正确的匹配。


3
Ben,很好的答案,它确实说明了模式保护的重要性。
JeffV

32

作为对问题精神的不回答,该精神询问如何将谓词合并到match子句中,在这种情况下,可以在以下条件之前排除谓词match

def assess(n: Int) {
  println(
    n compare 10 match {
      case 0 => "ten"
      case 1 => "greater than ten"
      case -1 => "less than ten"
    })
}

现在,的文档scala.math.Ordering.compare(T, T)仅保证不相等的结果将大于小于零。Java的Comparable#compareTo(T)指定与Scala的相似。像Scala 当前的实现一样,分别对正值和负值分别使用1和-1是很常规的,但是如果没有实现从底层更改的某些风险,就无法做出这样的假设。


5
我不确定您是否建议将其作为一个真正的解决方案,但是我强烈建议您不要依赖任何未记录的约定或假设。
本·詹姆斯

1
究竟。这就是为什么我写了“一个没有风险就无法做出这样的假设”,并将我的答案定为“非答案”的原因。考虑为什么 compare()并且compareTo()不指定0、1和-1作为它们的共域是很有趣的。
seh 2010年

4
Math.signum(N比较10)将保证-1,0或1
richj

1
今天早上,我证实,近6年写我原来的答复后,即使有问题的实现从一种类型转移到另一个,斯卡拉仍保持返回-1,0或1的是注意行为
SEH

2
一个有效的答案,但是我个人不喜欢这样。忘记0,1和-1意味着什么太容易了。
DanGordon '16

21

我认为一个解决方案比添加防护措施更具可读性:

(n compare 10).signum match {
    case -1 => "less than ten"
    case  0 => "ten"
    case  1 => "greater than ten"
}

笔记:

  • Ordered.compare如果小于此值,则返回一个负整数;大于或0等于则返回正数 。
  • Int.signum压缩从输出compare-1用于负数(小于10),1用于正(大于10),或0零(等于10)。

1

尽管以上所有和下面的答案都能很好地回答原始问题,但可以在文档https://docs.scala-lang.org/tour/pattern-matching.html中找到一些其他信息,但这些信息不适合我的情况但是由于这个stackoverflow答案是Google的第一个建议,因此我想发布我的答案,这是上述问题的一个特例。
我的问题是:

  • 如何在带有函数参数的匹配表达式中使用防护?

可以这样解释:

  • 如何在带有函数参数的匹配表达式中使用if语句?

答案是下面的代码示例:

    def drop[A](l: List[A], n: Int): List[A] = l match {
      case Nil => sys.error("drop on empty list")
      case xs if n <= 0 => xs
      case _ :: xs => drop(xs, n-1)
    }

链接到scala小提琴:https : //scalafiddle.io/sf/G37THif/2 ,您可以看到该case xs if n <= 0 => xs语句能够将n(一个函数的参数)与guard(if)语句一起使用。

我希望这可以帮助像我这样的人。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.