Scala正则表达式模式匹配是否正常工作?

时间:2013-03-04 02:02:35

标签: scala

我是Scala的新手,但有人告诉我"你正在检查" Toronto Raptor" == matchNY。" 以下代码段@ https://issues.scala-lang.org/browse/SI-7210,我真的不知道为什么" Totonto Raptor"是for循环中唯一与正则表达式匹配的字符串,有人可以解释一下吗? 谢谢。 大卫

    val matchNY = "^.*New.*$".r

    val teams = List(
        "Toronto Raptor",
        "New York Nets",
        "San Francisco 49ers",
        "Dallas Mavericks"
    )

    for (team <- teams) {
        team match {
            case `matchNY` => println("Go New York.")
            case _ => println("Boo")
        }
    }

注意 - 1:@ http://alvinalexander.com/scala/scala-unreachable-code-due-to-variable-pattern-message

解释了反引号的用法

3 个答案:

答案 0 :(得分:5)

我假设你的意思

val matchNY = "^.*New.*$".r

而不是^.New.$,如果您希望匹配包含New的字符串。

在Scala中,case语句块可以被认为是一个序列 部分功能。

在您的示例中,

case `matchNY` => // ...

转换为:

case x if x == matchNY  => // .. 

这样会尝试将String "Toronto Raptor"Regexp对象^.*New.*$匹配 使用等于

"Toronto Raptor" == ("^.*New.*$".r) 

哪个不匹配,因为StringRegexp对象是两个不同的东西。

列表中的任何其他String也是如此:

"New York Nets" !=  ("^.*New.*$".r)

哪个也不匹配。在case语句中使用正则表达式作为匹配的方法是:

case matchNY() => // .... Note the ()

其中,引擎盖(大致)等同于

case x matchNY.unapplySeq(x).isDefined =>  // ...

案例语句中的正则表达式实现为Extractor Objects unapplySeq方法。最后一个表达式显示了之前的内容 转化为。

如果matchNY有一个捕获,例如:

val matchNY = "^.*New York\s(.*)$".r

然后你可以用它来提取捕获的匹配:

case matchNY(something) => // 'something' is a String variable 
                           // with value "Nets"

旁注

您的示例可以缩小为

teams foreach { 
   case matchNY() => println("Go New York.")
   case _ => println("Boo")
}

答案 1 :(得分:4)

是的,它运作正常。模式匹配的神奇背后是extractors

如果您浏览Regex的ScalaDoc,您会发现它只定义了unapplySeq,而不是unapply

这意味着如果你想在模式匹配中使用正则表达式,你应该执行以下操作(注意matchNY后的括号):

val matchNY = "^.*New.*$".r

val teams = List(
    "Toronto Raptor",
    "New York Nets",
    "San Francisco 49ers",
    "Dallas Mavericks"
)

for (team <- teams) {
    team match {
        case matchNY() => println("Go New York.")
        case _ => println("Boo")
    }
}

否则,您只是检查列表中的元素是否为== matchNY,这不是您想要的。

答案 2 :(得分:1)

在你的for循环中,你真的要检查teams列表中的每个项目是否等于正则表达式matchNY,并且检查列表中的每个项目不仅仅是“Toronto Raptor”。这相当于你的for循环:

  for (team <- teams) {
    if (team == matchNY) println("Go New York.")
    else println("Boo")
  }

分解为:

  if ("Toronto Raptor" == matchNY) println("Go New York.") else println("Boo")
  if ("New York Nets" == matchNY) println("Go New York.") else println("Boo")
  if ("San Francisco 49ers" == matchNY) println("Go New York.") else println("Boo")
  if ("Dallas Mavericks" == matchNY) println("Go New York.") else println("Boo")

我认为你想要的是,如果匹配你的是正则表达式。你可以这样做:

  for (team <- teams) {
    matchNY.findFirstMatchIn(team) match {
      case Some(teamMatch) => {
        println("Go New York.")
        println(teamMatch)
      }
      case _ => {
        println("Boo")
        println(team)
      }
    }
  }

打印出来:

Boo
Toronto Raptor
Go New York.
New York Nets
Boo
San Francisco 49ers
Boo
Dallas Mavericks