Scala中更好的字符串格式

时间:2010-10-29 11:22:32

标签: string scala formatting string-formatting

由于参数太多,String.format很容易让人感到困惑。是否有更强大的格式化String的方法。像这样:

"This is #{number} string".format("number" -> 1)

或者这是不可能的,因为类型问题(format需要采用Map [String,Any],我假设;不知道这是否会使事情变得更糟。)

或者更好的方式是这样做:

val number = 1
<plain>This is { number } string</plain> text

即使它污染了名称空间?

修改

虽然在很多情况下可能会有一个简单的拉皮条,但我也在寻找与Python的format()相同的方向(参见:http://docs.python.org/release/3.1.2/library/string.html#formatstrings

7 个答案:

答案 0 :(得分:71)

在Scala 2.10中,您可以使用string interpolation

val height = 1.9d
val name = "James"
println(f"$name%s is $height%2.2f meters tall")  // James is 1.90 meters tall

答案 1 :(得分:38)

好吧,如果您唯一的问题是使参数的顺序更加灵活,可以轻松完成:

scala> "%d %d" format (1, 2)
res0: String = 1 2

scala> "%2$d %1$d" format (1, 2)
res1: String = 2 1

在地图的帮助下还可以替换正则表达式:

scala> val map = Map("number" -> 1)
map: scala.collection.immutable.Map[java.lang.String,Int] = Map((number,1))

scala> val getGroup = (_: scala.util.matching.Regex.Match) group 1
getGroup: (util.matching.Regex.Match) => String = <function1>

scala> val pf = getGroup andThen map.lift andThen (_ map (_.toString))
pf: (util.matching.Regex.Match) => Option[java.lang.String] = <function1>

scala> val pat = "#\\{([^}]*)\\}".r
pat: scala.util.matching.Regex = #\{([^}]*)\}

scala> pat replaceSomeIn ("This is #{number} string", pf)
res43: String = This is 1 string

答案 2 :(得分:17)

也许Scala-Enhanced-Strings-Plugin可以帮到你。看这里:

Scala-Enhanced-Strings-Plugin Documentation

答案 3 :(得分:14)

您可以轻松实现更丰富的格式化(使用pimp-my-library方法):

scala> implicit def RichFormatter(string: String) = new {
     |   def richFormat(replacement: Map[String, Any]) =
     |     (string /: replacement) {(res, entry) => res.replaceAll("#\\{%s\\}".format(entry._1), entry._2.toString)}
     | }
RichFormatter: (string: String)java.lang.Object{def richFormat(replacement: Map[String,Any]): String}

scala> "This is #{number} string" richFormat Map("number" -> 1)
res43: String = This is 1 string

答案 4 :(得分:8)

这是我来这里寻找的答案:

"This is %s string".format(1)

答案 5 :(得分:4)

如果您使用的是2.10,那么请使用内置插值。否则,如果你不关心极端性能而且不怕功能性单行,你可以使用fold +几个regexp扫描:

val template = "Hello #{name}!"
val replacements = Map( "name" -> "Aldo" )
replacements.foldLeft(template)((s:String, x:(String,String)) => ( "#\\{" + x._1 + "\\}" ).r.replaceAllIn( s, x._2 ))

答案 6 :(得分:2)

您可能还会考虑使用模板引擎来处理非常复杂的长字符串。最重要的是,我Scalate实现了Mustache模板引擎。

对于简单的字符串,可能会出现过度杀伤和性能损失,但您似乎处于开始变为真实模板的区域。