Как сопоставить шаблон с помощью регулярного выражения в Scala?
Я хотел бы иметь возможность найти совпадение между первой буквой слова и одной из букв в группе, такой как "ABC". В псевдокоде это может выглядеть примерно так:
case Process(word) =>
word.firstLetter match {
case([a-c][A-C]) =>
case _ =>
}
}
но как я могу захватить первую букву в Scala вместо Java? Как правильно выразить регулярное выражение? Возможно ли это сделать в пределах case class?
7 ответов:
вы можете сделать это, потому что регулярные выражения определяют экстракторы, но вам нужно сначала определить шаблон регулярного выражения. У меня нет доступа к Scala REPL, чтобы проверить это, но что-то вроде этого должно работать.
val Pattern = "([a-cA-C])".r word.firstLetter match { case Pattern(c) => c bound to capture group here case _ => }
начиная с версии 2.10, можно использовать функцию Строковой интерполяции Scala:
implicit class Regex(sc: StringContext) { def r = new util.matching.Regex(sc.parts.mkString, sc.parts.tail.map(_ => "x"): _*) } scala> "123" match { case r"\d+" => true case _ => false } res34: Boolean = trueеще лучше можно связать группы регулярных выражений:
scala> "123" match { case r"(\d+)$d" => d.toInt case _ => 0 } res36: Int = 123 scala> "10+15" match { case r"(\d\d)${first}\+(\d\d)${second}" => first.toInt+second.toInt case _ => 0 } res38: Int = 25также можно установить более детальные механизмы:
scala> object Doubler { def unapply(s: String) = Some(s.toInt*2) } defined module Doubler scala> "10" match { case r"(\d\d)${Doubler(d)}" => d case _ => 0 } res40: Int = 20 scala> object isPositive { def unapply(s: String) = s.toInt >= 0 } defined module isPositive scala> "10" match { case r"(\d\d)${d @ isPositive()}" => d.toInt case _ => 0 } res56: Int = 10впечатляющий пример того, что возможно с
Dynamicотображается в блоге введение в тип Dynamic:object T { class RegexpExtractor(params: List[String]) { def unapplySeq(str: String) = params.headOption flatMap (_.r unapplySeq str) } class StartsWithExtractor(params: List[String]) { def unapply(str: String) = params.headOption filter (str startsWith _) map (_ => str) } class MapExtractor(keys: List[String]) { def unapplySeq[T](map: Map[String, T]) = Some(keys.map(map get _)) } import scala.language.dynamics class ExtractorParams(params: List[String]) extends Dynamic { val Map = new MapExtractor(params) val StartsWith = new StartsWithExtractor(params) val Regexp = new RegexpExtractor(params) def selectDynamic(name: String) = new ExtractorParams(params :+ name) } object p extends ExtractorParams(Nil) Map("firstName" -> "John", "lastName" -> "Doe") match { case p.firstName.lastName.Map( Some(p.Jo.StartsWith(fn)), Some(p.`.*(\w)$`.Regexp(lastChar))) => println(s"Match! $fn ...$lastChar") case _ => println("nope") } }
как delnan указал,
matchключевое слово в Scala не имеет ничего общего с регулярными выражениями. Чтобы узнать, соответствует ли строка регулярному выражению, вы можете использоватьString.matchesметод. Чтобы узнать, начинается ли строка с a, b или c в Нижнем или верхнем регистре, регулярное выражение будет выглядеть следующим образом:word.matches("[a-cA-C].*")вы можете прочитать это регулярное выражение как "один из символов a, b, c, A, B или C, за которым следует что-либо" (
.означает "любой символ" и*означает "ноль или более раз", так ".* "есть ли строка.)
чтобы немного расширить на Эндрю: тот факт, что регулярные выражения определяют экстракторы, можно использовать для декомпозиции подстрок, соответствующих регулярному выражению, очень хорошо используя сопоставление шаблонов Scala, например:
val Process = """([a-cA-C])([^\s]+)""".r // define first, rest is non-space for (p <- Process findAllIn "aha bah Cah dah") p match { case Process("b", _) => println("first: 'a', some rest") case Process(_, rest) => println("some first, rest: " + rest) // etc. }
обратите внимание, что подход из ответа @AndrewMyers соответствует весь строку в регулярное выражение, с эффектом привязки регулярного выражения на обоих концах строки, используя
^и$. Пример:scala> val MY_RE = "(foo|bar).*".r MY_RE: scala.util.matching.Regex = (foo|bar).* scala> val result = "foo123" match { case MY_RE(m) => m; case _ => "No match" } result: String = foo scala> val result = "baz123" match { case MY_RE(m) => m; case _ => "No match" } result: String = No match scala> val result = "abcfoo123" match { case MY_RE(m) => m; case _ => "No match" } result: String = No matchи
.*в конце:scala> val MY_RE2 = "(foo|bar)".r MY_RE2: scala.util.matching.Regex = (foo|bar) scala> val result = "foo123" match { case MY_RE2(m) => m; case _ => "No match" } result: String = No match
строку.совпадения-это способ сделать сопоставление шаблонов в смысле регулярных выражений.
но как удобно в сторону, слово.firstLetter в реальном коде Scala выглядит так:
word(0)Scala рассматривает строки как последовательность символов, поэтому, если по какой-то причине вы хотите явно получить первый символ строки и сопоставить его, вы можете использовать что-то вроде этого:
"Cat"(0).toString.matches("[a-cA-C]") res10: Boolean = trueЯ не предлагаю это как общий способ сделать сопоставление шаблонов регулярных выражений, но это соответствует вашим предлагаемый подход заключается в том, чтобы сначала найти первый символ строки, а затем сопоставить его с регулярным выражением.
изменить: Чтобы быть ясным, я бы сделал это так, как другие сказали:
"Cat".matches("^[a-cA-C].*") res14: Boolean = trueпросто хотел показать пример как можно ближе к первоначальной псевдокод. Ура!
Сначала мы должны знать, что регулярное выражение может использоваться отдельно. Вот пример:
import scala.util.matching.Regex val pattern = "Scala".r // <=> val pattern = new Regex("Scala") val str = "Scala is very cool" val result = pattern findFirstIn str result match { case Some(v) => println(v) case _ => } // output: Scalaval date = """(\d\d\d\d)-(\d\d)-(\d\d)""".r "2014-11-20" match { case date(year, month, day) => "hello" } // output: helloна самом деле, регулярное выражение само по себе уже очень мощное; единственное, что нам нужно сделать, это сделать его более мощным с помощью Scala. Вот несколько примеров в документе Скала : http://www.scala-lang.org/files/archive/api/current/index.html#scala.util.matching.Regex
Comments