2014-11-02 4 views
2

Я пытаюсь рассуждать о том, как работает понимание, потому что он делает что-то отличное от того, что я ожидаю от него. Я прочитал несколько ответов, наиболее актуальным из которых является этот Scala "<-" for comprehension Однако я все еще недоумеваю.Scala regex и для понимания

Следующий код работает как ожидается. Он печатает строки, где значения совпадающая с помощью двух различных регулярных выражений не равны (по одному для значения в куки сессии, а другой для значения в GET аргументах, просто чтобы дать контекст):

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 
+1

Не уверен, что это актуально, но ваша вторая версия появляется (с первого взгляда), чтобы иметь отличие от первой версии: в строке 'whidSession <- ...' часть 'mkString '' ' внутри {} вместо внешнего, как это было в первом случае. Ошибка? –

+0

В первом фрагменте вы используете regex 'rWhidArg', но во втором' rWhidEOL'. Может быть, ваше второе регулярное выражение соответствует каждому символу? –

ответ

1

Для того, чтобы проверить, что соответствующие матчи равны:

но позволяют несколько матчей на линии:

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.

Смежные вопросы