Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Better String formatting in Scala

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)

like image 451
Debilski Avatar asked Oct 29 '10 11:10

Debilski


People also ask

What is the easiest way to format string in Scala?

In Scala Formatting of strings can be done utilizing two methods namely format() method and formatted() method. These methods have been approached from the Trait named StringLike.

What is ${} in Scala?

Using expressions in string literals According to the official string interpolation documentation, “Any arbitrary expression can be embedded in ${} .” In the following example, the value 1 is added to the variable age inside the string: scala> println(s"Age next year: ${age + 1}") Age next year: 34.

What is F interpolation in Scala?

The f Interpolator Prepending f to any string literal allows the creation of simple formatted strings, similar to printf in other languages. When using the f interpolator, all variable references should be followed by a printf -style format string, like %d . Let's look at an example: Scala 2 and 3.

What does string * mean in Scala?

In Scala, as in Java, a string is an immutable object, that is, an object that cannot be modified. On the other hand, objects that can be modified, like arrays, are called mutable objects. Strings are very useful objects, in the rest of this section, we present important methods of java. lang.


3 Answers

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
like image 133
Andrej Herich Avatar answered Nov 21 '22 15:11

Andrej Herich


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
like image 24
Daniel C. Sobral Avatar answered Nov 21 '22 16:11

Daniel C. Sobral


You can easily implement a richer formatting yourself (with the "enhance 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

Or on more recent Scala versions since the original answer:

implicit class RichFormatter(string: String) {
  def richFormat(replacement: Map[String, Any]): String =
    replacement.foldLeft(string) { (res, entry) =>
      res.replaceAll("#\\{%s\\}".format(entry._1), entry._2.toString)
    }
}
like image 23
Vasil Remeniuk Avatar answered Nov 21 '22 17:11

Vasil Remeniuk