假设我正在编写一个简单的函数来转义XML字符串。
val map = Map('&' -> "&", '<' -> "<", '>' -> ">") // ... and more
def escape(str: String): String = {
val w = new java.io.StringWriter()
for(c <- str) if (map.contains(c)) w.write(map(c)) else w.write(c);
w.toString
}
它在Scala中看起来不是惯用的,而且,我不知道如何处理map
,它将字符映射到转义字符串。你会怎么建议我解决它?
答案 0 :(得分:10)
现实解决方案
scala> scala.xml.Utility.escape(foo)
res7: String = &foo<bar>hello
如果您仍然有兴趣自己动手:
首先,没有必要在转义地图中重复&
和;
部分:
scala> val Escapes = Map('&' -> "amp", '<' -> "lt", '>' -> "gt")
(将它们放入其中更简单,更快......但是因为你似乎已经将这个问题用于学习目的......)
scala> def escapeChar(c: Char) = Escapes.get(c).map { x => s"&$x;" }
escapeChar: (c: Char)Option[String]
scala> def escapeStr(s: String) = s.flatMap { c => escapeChar(c).getOrElse(c.toString) }
escapeStr: (s: String)String
scala> escapeStr("&foo<bar>hello")
res9: String = &foo<bar>hello
...您也可以内联escapeChar(c: Char)
函数,但我认为这样更具可读性。
如果您感兴趣:这可以通过将字符串视为一系列字符来实现;你flatMap
,它允许你将每个char映射到多个char(String
);然后flatMap
将所有发出的字符串连接成一个字符串。不需要转义的字符可以简单地映射到一个字符串。
答案 1 :(得分:5)
只是为了完整性 - 基本上是相同的解决方案,但用 function 方法代替地图:
def escape(char: Char) = char match {
case '&' => "&"
case '<' => "<"
case '>' => ">"
case noEscaping => noEscaping.toString
}
val str = "hit & run"
str.flatMap(escape)
// hit & run
答案 2 :(得分:4)
这个怎么样:
scala> val map = Map[Char, Seq[Char]]('&' -> "&",
'<' -> "<",
'>' -> ">").withDefault(x => Seq(x))
map: scala.collection.immutable.Map[Char,Seq[Char]] = Map(& -> &, < -> <, > -> >)
scala> "&foo<bar>hello".flatMap(map)
res2: String = &foo<bar>hello
OR
scala> val map = Map('&' -> "&", '<' -> "<", '>' -> ">").withDefault(identity)
scala> "&foo<bar>hello".map(map).mkString
res3: String = &foo<bar>hello