Scala match case if条件守卫和正则表达式匹配

2019-05-04 20:23:02 | 编辑 | 添加

1.case中的guard 条件守卫语句

在模式匹配中使用字面量的好处很多,但有时你却需要添加其他的逻辑:

  for (i <- Seq(1,2,3,4)) {
    i match {
      case _ if i%2 == 0 => println(s"even: $i") // 只有当i 为偶数时才匹配。我们用_ 代替变量名,因为我们已经有i 可以作为变量名了。
      case _ => println(s"odd: $i") // 匹配上一case 子句相对的另一种可能性,即i 为奇数。
    }
  }


以上代码的输出为:

odd: 1
even: 2
odd: 3
even: 4

注意,if 表达式的两边不需要使用括号,就像我们在for 表达式中也不需要括号一样。


2.match case 正则表达式的匹配

正则表达式可以很方便地从符合特定结构的字符串中提取数据。

Scala 封装了Java 的正则表达式。以下给出一个示例:


val BookExtractorRE = """Book: title=([^,]+),\s+author=(.+)""".r // 该正则表达式匹配一个用于表示书本的字符串,其中有两个捕捉组(注意正则表达式中的括号),一个表示标题,一个表示作者。调用r 方法以创建正则表达式。第二个正则表达式匹配一个用于表示杂志的字符串,其中的捕捉组表示杂志标题和发行时间。
  val MagazineExtractorRE = """Magazine: title=([^,]+),\s+issue=(.+)""".r
  val catalog = Seq(
    "Book: title=Programming Scala Second Edition, author=Dean Wampler",
    "Magazine: title=The New Yorker, issue=January 2014",
    "Unknown: text=Who put this here??"
  )
  for (item <- catalog) {
    item match {
      case BookExtractorRE(title, author) => // 用法与case 类相似,与捕捉组相匹配的字符串被提取出来,赋值给变量。
        println(s"""Book "$title", written by $author""")
      case MagazineExtractorRE(title, issue) =>
        println(s"""Magazine "title", issue $issue""")
      case entry => println(s"Unrecognized entry: $entry")
    }
  }


运行的输出为:

Book "Programming Scala Second Edition", written by Dean Wampler
Magazine "The New Yorker", issue January 2014
Unrecognized entry: Unknown: text=Who put this here??


我们用三重双引号来表示正则表达式字符串,否则,就不得不对正则表达式的反斜杠进行转义,例如用\\s 表示\s。你还可以通过创建一个Regex 类的实例来定义正则表达式,如new Regex("""\W"""),但这种用法并不常见。


在三个双引号内的正则表达式中使用变量插值是无效的。你依然需要对变量插值进行转义,例如,你应该用s"""$first\\s+$second""".r,而不是s"""$first\s+$second""".r。而如果你没有使用变量插值,则不必转义。


scala.util.matching.Regex 定义了若干个用于正则表达式其他操作的方法,如查找和替换。