wake-up-neo.com

Bessere String Formatierung in Scala

Bei zu vielen Argumenten wird String.format Leicht zu verwirrend. Gibt es eine leistungsfähigere Möglichkeit, einen String zu formatieren? Wie so:

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

Oder ist dies aufgrund von Typproblemen nicht möglich (format würde vermutlich eine Map [String, Any] benötigen; ich weiß nicht, ob dies die Situation verschlimmern würde).

Oder geht das besser so:

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

obwohl es den Namensraum verschmutzt?

Bearbeiten:

In vielen Fällen reicht ein einfaches Zuhalten, aber ich suche auch nach etwas, das in die gleiche Richtung geht wie Pythons format() (Siehe: http://docs.python.org/release/ 3.1.2/library/string.html # formatstrings )

55
Debilski

In Scala 2.10 können Sie String-Interpolation verwenden.

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

Nun, wenn Ihr einziges Problem darin besteht, die Reihenfolge der Parameter flexibler zu gestalten, können Sie dies ganz einfach tun:

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

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

Und es gibt auch Regex-Ersatz mit Hilfe einer Karte:

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
38

Vielleicht hilft Ihnen das Scala-Enhanced-Strings-Plugin. Schau hier:

Scala-Enhanced-Strings-Plugin-Dokumentation

17
Ruediger Keller

Sie können eine umfangreichere Formatierung einfach selbst implementieren (mit dem Ansatz von 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
14
Vasil Remeniuk

Dies ist die Antwort, die ich hier gesucht habe:

"This is %s string".format(1)
9
Priyank Desai

Wenn Sie 2.10 verwenden, verwenden Sie die integrierte Interpolation. Andernfalls können Sie, wenn Sie sich nicht für extreme Leistung interessieren und keine Angst vor funktionierenden Einzeilern haben, eine Falz- und mehrere Regexp-Scans verwenden:

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

Sie können auch die Verwendung einer Template-Engine für sehr komplexe und lange Zeichenfolgen in Betracht ziehen. Auf meinem Kopf habe ich Scalate , das unter anderem die Moustache Template-Engine implementiert.

Könnte für einfache Saiten ein Overkill und ein Leistungsverlust sein, aber Sie scheinen sich in dem Bereich zu befinden, in dem sie anfangen, echte Vorlagen zu werden.

2
Dominik Bucher