【问题标题】:Scala regex and for comprehensionScala 正则表达式和理解
【发布时间】:2014-11-03 22:11:44
【问题描述】:

我试图解释 for 理解是如何工作的,因为它正在做一些与我期望它不同的事情。我看了几个答案,其中最相关的是这个Scala "<-" for comprehension 但是,我仍然感到困惑。

以下代码按预期工作。它打印两个不同正则表达式匹配的值不相等的行(一个用于会话 cookie 中的值,另一个用于 GET args 中的值,只是为了提供上下文):

  file.getLines().foreach { line =>
      val whidSession: String = rWhidSession.findAllMatchIn(line) flatMap {m => m.group(1)} mkString ""
      val whidArg: String = rWhidArg.findAllMatchIn(line) flatMap {m => m.group(1)} mkString ""
      if(whidSession != whidArg) println(line)
  }

以下是有问题的代码,它对匹配字符串中的字母进行迭代,因此在两个值中有不同的字母时会多次打印该行:

  /**
   * This would compare letters, regardless of the use of mkString.. even without the flatMap step.
   */

  val whidTuples = for {
    line <- file.getLines().toList
    whidSession <- rWhidSession.findAllMatchIn(line) flatMap {m => m.group(1) mkString ""}
    whidArg <- rWhidEOL.findAllMatchIn(line) flatMap {m => m.group(1) mkString ""} if whidArg != whidSession 
  } yield line

【问题讨论】:

  • 不确定这是否相关,但您的第二个版本出现(无论如何一目了然)与第一个版本有所不同:在whidSession &lt;- ... 行中,mkString "" 部分位于{} 而不是第一种情况下的外部。错误?
  • 在第一个 sn-p 中,您使用正则表达式 rWhidArg,但在第二个中使用 rWhidEOL。也许您的第二个正则表达式在每个符号中都匹配?

标签: scala for-comprehension


【解决方案1】:

检查对应的匹配是否相等:

scala> val ss = "foo/foo" :: "bar/bar" :: "foo/bar" :: Nil
ss: List[String] = List(foo/foo, bar/bar, foo/bar)

scala> val ra = "(.*)/.*".r ; val rb = ".*/(.*)".r
ra: scala.util.matching.Regex = (.*)/.*
rb: scala.util.matching.Regex = .*/(.*)

scala> for (s <- ss; ra(x) = s; rb(y) = s if x != y) yield s
res0: List[String] = List(foo/bar)

但允许一行中有多个匹配项:

scala> val ss = "foo/foo" :: "bar/bar" :: "baz/baz foo/bar" :: Nil
ss: List[String] = List(foo/foo, bar/bar, baz/baz foo/bar)

这仍然会比较第一个匹配项:

scala> val ra = """(\w*)/\w*""".r.unanchored ; val rb = """\w*/(\w*)""".r.unanchored
ra: scala.util.matching.UnanchoredRegex = (\w*)/\w*
rb: scala.util.matching.UnanchoredRegex = \w*/(\w*)

scala> for (s <- ss; ra(x) = s; rb(y) = s if x != y) yield s
res2: List[String] = List()

所以比较所有匹配:

scala> val ra = """(\w*)/\w*""".r ; val rb = """\w*/(\w*)""".r
ra: scala.util.matching.Regex = (\w*)/\w*
rb: scala.util.matching.Regex = \w*/(\w*)

scala> for (s <- ss; ma <- ra findAllMatchIn s; mb <- rb findAllMatchIn s; ra(x) = ma; rb(y) = mb if x != y) yield s
res3: List[String] = List(baz/baz foo/bar, baz/baz foo/bar, baz/baz foo/bar)

scala> for (s <- ss; (ma, mb) <- (ra findAllMatchIn s) zip (rb findAllMatchIn s); ra(x) = ma; rb(y) = mb if x != y) yield s
res4: List[String] = List(baz/baz foo/bar)

scala> for (s <- ss; (ra(x), rb(y)) <- (ra findAllMatchIn s) zip (rb findAllMatchIn s) if x != y) yield s
res5: List[String] = List(baz/baz foo/bar)

匹配ra(x) = ma 不应该重新评估正则表达式,而只是做ma group 1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-17
    • 2017-11-25
    • 2013-09-19
    • 2018-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多