这是我之前question
的后续内容感谢答案,我意识到escape
函数实际上是 flatMap
,其参数为f:Char => Seq[Char]
,用于将转义字符映射到转义序列(请参阅答案) )。
现在我想知道如何将unescape
作为反向操作实施到escape
。我想这应该与flatMap
相反,参数为f:Seq[Char] => Char
。是否有意义 ?您如何建议实施unescape
?
答案 0 :(得分:2)
我想这应该是与flatMap相反的函数f:Seq [Char] =>字符。是否有意义 ?
不是真的。您的反函数f:Seq[Char] => Char
应该在"abc"
上返回什么?它应该适用于任何字符序列并返回单个字符。您可以尝试使用PartialFunction[Seq[Char], Char]
,但是您会遇到其他问题。您是否将其应用于输入的每个后续步骤?
更通用的解决方案是将foldLeft
与累加器类型一起使用,该累加器类型包含结果的构建部分和转义序列,类似于(未经测试):
def unescape(str: String) = {
val result = str.foldLeft[(String, Option[String])](("", None)) { case ((acc, escapedAcc), c) =>
(c, escapedAcc) match {
case ('&', None) =>
(acc, Some(""))
case (_, None) =>
(acc + c, None)
case ('&', Some(_)) =>
throw new IllegalArgumentException("nested escape sequences")
case (';', Some(escapedAcc1)) =>
(acc + unescapeMap(escapedAcc1), None)
case (_, Some(escapedAcc1)) =>
(acc, Some(escapedAcc1 + c))
}
}
result match {
case (escaped, None) =>
escaped
case (_, Some(_)) =>
throw new IllegalArgumentException("unfinished escape sequence")
}
}
val unescapeMap = Map("amp" -> "&", "lt" -> "<", ...)
(将StringBuilder
用于累加器会更有效,但这更容易理解。)
但是对于这个特定情况,您可以将字符串拆分为&
,然后将除;
之外的每个部分分开,然后以这种方式获取您想要的部分。
答案 1 :(得分:1)
这似乎是my own answer到the question的后续行动,其后续问题是......使用scala.xml.Utility.unescape
:
val sb = new StringBuilder
scala.xml.Utility.unescape("amp", sb)
println(sb.toString) // prints &
或者如果你只想忘记一次并扔掉StringBuilder
实例:
scala.xml.Utility.unescape("amp", new StringBuilder).toString // returns "&"
这只是解析个人逃脱;你必须自己构建一个包含整个XML字符串的解析器 - 接受的答案似乎提供了一点但却无法重新发明scala.xml.Utility
轮 - 或者使用来自scala.xml
的东西。