Better String formatting in Scala

本小妞迷上赌 提交于 2019-11-26 19:13:56

问题


With too many arguments, String.format easily gets too confusing. Is there a more powerful way to format a String. Like so:

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

Or is this not possible because of type issues (format would need to take a Map[String, Any], I assume; don’t know if this would make things worse).

Or is the better way doing it like this:

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

even though it pollutes the name space?

Edit:

While a simple pimping might do in many cases, I’m also looking for something going in the same direction as Python’s format() (See: http://docs.python.org/release/3.1.2/library/string.html#formatstrings)


回答1:


In Scala 2.10 you can use 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



回答2:


Well, if your only problem is making the order of the parameters more flexible, this can be easily done:

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

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

And there's also regex replacement with the help of a map:

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



回答3:


Maybe the Scala-Enhanced-Strings-Plugin can help you. Look here:

Scala-Enhanced-Strings-Plugin Documentation




回答4:


You can easily implement a richer formatting yourself (with pimp-my-library approach):

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



回答5:


This the answer I came here looking for:

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



回答6:


If you're using 2.10 then go with built-in interpolation. Otherwise, if you don't care about extreme performance and are not afraid of functional one-liners, you can use a fold + several regexp scans:

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



回答7:


You might also consider the use of a template engine for really complex and long strings. On top of my head I have Scalate which implements amongst others the Mustache template engine.

Might be overkill and performance loss for simple strings, but you seem to be in that area where they start becoming real templates.



来源:https://stackoverflow.com/questions/4051308/better-string-formatting-in-scala

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!