[英]How to implement “unescape” in Scala?
这是我先前问题的跟进
多亏了答案,我才意识到escape
函数实际上是一个带有参数f:Char => Seq[Char]
的flatMap
,用于将转义字符映射到转义序列(请参见答案)。
现在,我想知道如何将unescape
实现为反向操作以进行escape
。 我猜tt应该与参数f:Seq[Char] => Char
flatMap
相反。 是否有意义 ? 您如何建议实施unescape
?
我想tt应该是带有函数f:Seq [Char] => Char的flatMap的反向版本。 是否有意义 ?
并不是的。 您的反函数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
效率更高,但这更容易理解。)
但是对于这种特定情况,您可以只在&
上分割字符串,然后分割除第一部分外的每个部分;
,并以此方式获取所需零件。
这似乎是我 对该问题的回答的后续问题 , 该问题的后续问题是...使用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
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.