Pum*_*ath 2 regex scala matching
我开始学习 Scala 并想使用正则表达式来匹配字符串中的字符,以便我可以填充字符及其值(字符串值、数字等)的可变映射,然后打印结果。
我已经查看了关于 SO 的几个答案并浏览了 Scala Docs,但似乎无法正确理解。我有一个简短的 Lexer 类,目前看起来像这样:
class Lexer {
private val tokens: mutable.Map[String, Any] = collection.mutable.Map()
private def checkCharacter(char: Character): Unit = {
val Operator = "[-+*/^%=()]".r
val Digit = "[\\d]".r
val Other = "[^\\d][^-+*/^%=()]".r
char.toString match {
case Operator(c) => tokens(c) = "Operator"
case Digit(c) => tokens(c) = Integer.parseInt(c)
case Other(c) => tokens(c) = "Other" // Temp value, write function for this
}
}
def lex(input: String): Unit = {
val inputArray = input.toArray
for (s <- inputArray)
checkCharacter(s)
for((key, value) <- tokens)
println(key + ": " + value)
}
}
Run Code Online (Sandbox Code Playgroud)
我对那种奇怪的方法语法 Operator(c) 感到非常困惑,我已经看到它被用来处理要匹配的值,并且我也不确定这是否是在 Scala 中使用正则表达式的正确方法。我想我想要这段代码做的很清楚,我真的很感激理解这一点的一些帮助。如果需要更多信息,我会提供我能提供的
这个官方文档有很多例子: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)
Run Code Online (Sandbox Code Playgroud)
您regex将成为一个对象,它具有一些有用的方法可以找到匹配的组,例如findAllIn.
在 Scala 中,使用模式匹配来安全提取值是惯用的,因此Regex类也有unapplySeq支持模式匹配的方法。这使它成为提取器对象。您可以直接使用它(不常见):
scala> regex.unapplySeq("something")
res1: Option[List[String]] = Some(List(something))
Run Code Online (Sandbox Code Playgroud)
或者您可以让 Scala 编译器在您进行模式匹配时为您调用它:
scala> "something" match {
| case regex(x) => x
| case _ => ???
| }
res2: String = something
Run Code Online (Sandbox Code Playgroud)
你可能会问为什么这个返回类型在unapply/unapplySeq. 该文档很好地解释了它:
unapply 的返回类型应选择如下:
Run Code Online (Sandbox Code Playgroud)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)].有时,要提取的值的数量不是固定的,我们希望根据输入返回任意数量的值。对于此用例,您可以使用返回 Option[Seq[T]] 的 unapplySeq 方法定义提取器。这些模式的常见示例包括使用 case List(x, y, z) => 解构 List 和使用正则表达式 Regex 分解 String,例如 case r(name, remainingFields @ _*) =>
简而言之,您的正则表达式可能匹配一个或多个组,因此您需要返回一个列表/序列。它必须被包裹在一个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
Run Code Online (Sandbox Code Playgroud)