web-dev-qa-db-fra.com

Meilleur formatage des chaînes dans Scala

Avec trop d'arguments, String.format Devient facilement trop confus. Existe-t-il un moyen plus puissant de formater une chaîne. Ainsi:

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

Ou est-ce impossible en raison de problèmes de type (format devrait prendre une Map [String, Any], je suppose; je ne sais pas si cela aggraverait les choses).

Ou est la meilleure façon de le faire comme ceci:

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

même s'il pollue l'espace de nom?

Modifier:

Bien qu'un simple proxénétisme puisse faire dans de nombreux cas, je cherche également quelque chose qui va dans le même sens que la fonction format() de Python (voir: http://docs.python.org/release/ 3.1.2/library/string.html # formatstrings )

55
Debilski

Dans Scala 2.10 vous pouvez utiliser interpolation de chaîne .

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

Eh bien, si votre seul problème est de rendre l'ordre des paramètres plus flexible, cela peut être facilement fait:

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

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

Et il y a aussi le remplacement de regex à l'aide d'une carte:

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
Daniel C. Sobral

Peut-être que le plug-in Scala-Enhanced-Strings peut vous aider. Regardez ici:

Documentation Scala-Enhanced-Strings-Plugin

17
Ruediger Keller

Vous pouvez facilement implémenter vous-même un formatage plus riche (avec l'approche 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

Voici la réponse que je suis venue chercher ici:

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

Si vous utilisez 2.10, optez pour l'interpolation intégrée. Sinon, si vous ne vous souciez pas des performances extrêmes et n'avez pas peur des lignes simples fonctionnelles, vous pouvez utiliser un scan de pli + plusieurs expressions rationnelles:

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

Vous pouvez également envisager l'utilisation d'un moteur de modèle pour les chaînes très complexes et longues. Au sommet de ma tête, j'ai Scalate qui implémente entre autres le moteur de modèle Moustache .

Cela peut être exagéré et une perte de performances pour les chaînes simples, mais vous semblez être dans ce domaine où ils commencent à devenir de vrais modèles.

2
Dominik Bucher