В этом официальном документе много примеров: https://www.scala -lang.org / api / 2.12.1 / scala / util / matching / Regex.html . Что может сбить с толку, так это тип регулярного выражения и его использование при сопоставлении с образцом ...
Вы можете создать регулярное выражение из любой строки, используя .r
:
scala> val regex = "(something)".r
regex: scala.util.matching.Regex = (something)
Вашregex
становится объектом, который имеет несколько полезных методов для поиска подходящих групп, таких как findAllIn
.
В Scala идиоматично использовать сопоставление с образцом для безопасного извлечения значений, таким образом, класс Regex
такжеимеет unapplySeq
метод для поддержки сопоставления с образцом. Это делает его объектом-экстрактором . Вы можете использовать его напрямую (не часто):
scala> regex.unapplySeq("something")
res1: Option[List[String]] = Some(List(something))
или позволить компилятору Scala вызывать его для вас при сопоставлении с образцом:
scala> "something" match {
| case regex(x) => x
| case _ => ???
| }
res2: String = something
Вы можете спросить, почему именно этотип возврата на unapply/unapplySeq
. Документ объясняет это очень хорошо:
Тип возвращаемого значения неприменяемого следует выбирать следующим образом:
If it is just a test, return a Boolean. For instance case even().
If it returns a single sub-value of type T, return an Option[T].
If you want to return several sub-values T1,...,Tn, group them in an optional tuple Option[(T1,...,Tn)].
Иногда количество извлекаемых значений не является фиксированным имы хотели бы вернуть произвольное количество значений, в зависимости от ввода. Для этого варианта использования вы можете определить экстракторы с помощью метода unapplySeq, который возвращает Option [Seq [T]]. Типичные примеры этих шаблонов включают деконструкцию List с использованием case List (x, y, z) => и декомпозицию String с использованием регулярного выражения Regex, такого как case r (name, ОстальноеFields @ _ *) =>
Короче говоря, ваше регулярное выражение может соответствовать одной или нескольким группам, поэтому вам нужно вернуть список / секв. Это должно быть заключено в Option
, чтобы соответствовать контракту экстрактора.
То, как вы используете регулярное выражение, является правильным, я бы просто отобразил вашу функцию во входном массиве, чтобы избежать создания изменяемых карт. Возможно, что-то вроде этого:
class Lexer {
private def getCharacterType(char: Character): Any = {
val Operator = "([-+*/^%=()])".r
val Digit = "([\\d])".r
//val Other = "[^\\d][^-+*/^%=()]".r
char.toString match {
case Operator(c) => "Operator"
case Digit(c) => Integer.parseInt(c)
case _ => "Other" // Temp value, write function for this
}
}
def lex(input: String): Unit = {
val inputArray = input.toArray
val tokens = inputArray.map(x => x -> getCharacterType(x))
for((key, value) <- tokens)
println(key + ": " + value)
}
}
scala> val l = new Lexer()
l: Lexer = Lexer@60f662bd
scala> l.lex("a-1")
a: Other
-: Operator
1: 1