Comment utiliser java.String.format dans Scala?

322

J'essaie d'utiliser une .formatméthode de chaîne. Mais si je place% 1,% 2, etc. dans la chaîne, java.util.UnknownFormatConversionException est levée pointant vers un morceau de code source Java déroutant:

private void checkText(String s) {

    int idx;

    // If there are any '%' in the given string, we got a bad format
    // specifier.
    if ((idx = s.indexOf('%')) != -1) {
        char c = (idx > s.length() - 2 ? '%' : s.charAt(idx + 1));
        throw new UnknownFormatConversionException(String.valueOf(c));
    }
}

D'après cela, je comprends que l' %omble est interdit. Si oui, que dois-je utiliser pour les espaces réservés d'argument?

J'utilise Scala 2.8.

Ivan
la source

Réponses:

302

Bien que toutes les réponses précédentes soient correctes, elles sont toutes en Java. Voici un exemple Scala:

val placeholder = "Hello %s, isn't %s cool?"
val formatted = placeholder.format("Ivan", "Scala")

J'ai également un article de blog sur la façon de faire formatcomme l' %opérateur de Python qui pourrait être utile.

pr1001
la source
2
Beaucoup d'exemples dans la documentation JDK: docs.oracle.com/javase/7/docs/api/java/util/…
angelcervera
1
Vous pouvez simplifier en appliquant formatdirectement au littéral de chaîne:"Hello %s, isn't %s cool?".format("Ivan", "Scala")
sotrh
298

Vous n'avez pas besoin d'utiliser des chiffres pour indiquer le positionnement. Par défaut, la position de l'argument est simplement l'ordre dans lequel il apparaît dans la chaîne.

Voici un exemple de la bonne façon de l'utiliser:

String result = String.format("The format method is %s!", "great");
// result now equals  "The format method is great!".

Vous utiliserez toujours un %suivi de quelques autres caractères pour indiquer à la méthode comment elle doit afficher la chaîne. %sest probablement le plus courant, et cela signifie simplement que l'argument doit être traité comme une chaîne.

Je n'énumérerai pas toutes les options, mais je donnerai quelques exemples juste pour vous donner une idée:

// we can specify the # of decimals we want to show for a floating point:
String result = String.format("10 / 3 = %.2f", 10.0 / 3.0);
// result now equals  "10 / 3 = 3.33"

// we can add commas to long numbers:
result = String.format("Today we processed %,d transactions.", 1000000);
// result now equals  "Today we processed 1,000,000 transactions."

String.formatutilise simplement un java.util.Formatter, donc pour une description complète des options, vous pouvez voir les javadocs du formateur .

Et, comme le mentionne BalusC, vous verrez dans la documentation qu'il est possible de modifier l'ordre des arguments par défaut si nécessaire. Cependant, probablement la seule fois où vous auriez besoin / voudriez faire ceci est si vous utilisez le même argument plus d'une fois.

TM.
la source
127

Au lieu de regarder le code source, vous devriez lire la syntaxe javadoc String.format () et Formatter .

Vous spécifiez le format de la valeur après le%. Par exemple, pour un entier décimal, c'est dpour String et c'est s:

String aString = "world";
int aInt = 20;
String.format("Hello, %s on line %d",  aString, aInt );

Production:

Hello, world on line 20

Pour faire ce que vous avez essayé (utiliser un argument index), vous utilisez: *n*$,

String.format("Line:%2$d. Value:%1$s. Result: Hello %1$s at line %2$d", aString, aInt );

Production:

Line:20. Value:world. Result: Hello world at line 20
OscarRyz
la source
70

Vous pouvez l'utiliser;

String.format("%1$s %2$s %2$s %3$s", "a", "b", "c");

Production:

abbc

Engin Ardıç
la source
1
Je n'ai jamais vu ce genre d'utilisation, c'est très utile lors de la répétition de cordes, super!
Domi.Zhang
8
+1, cela ressemble plus à ce que vous utilisez en tant que développeur C #. Là, nous utilisons {0}et {1}au lieu de %1$et %2$.
ashes999
@ ashes999 Je viens aussi de c # land. Je suis tellement habitué aux crochets numérotés que j'avais oublié que ce n'était pas la façon standard de faire les choses. Voir les signes de pourcentage ramène tout cela!
JonnyRaa
13

Notez également que Scala étend String avec un certain nombre de méthodes (via une conversion implicite en une WrappedString introduite par Predef), vous pouvez donc également effectuer les opérations suivantes:

val formattedString = "Hello %s, isn't %s cool?".format("Ivan", "Scala")
denis phillips
la source
11

La référence officielle est la classe Formatter.

Alberto Segura
la source
10

Dans Scala 2.10

val name = "Ivan"
val weather = "sunny"

s"Hello $name, it's $weather today!"
Londo
la source
1
Je suppose qu'il s'agit simplement d'une syntaxe spéciale de concaténation de chaînes (ce qui signifie que $ name et $ weather sont des références dures aux variables définies précédemment). String.Format prend cependant le modèle en paramètre et permet ainsi par exemple de récupérer le modèle à partir d'un fichier de propriétés et autres. - Est-ce possible avec la syntaxe ci-dessus?
chiccodoro
C'est ce qu'on appelle l'interpolation de chaîne, dans scala il y a deux types: s "" et f "", le 's' est une chaîne simple et le 'f' est similaire au printf, vous pouvez même définir votre propre interpolation (je n'ai pas essayer). Les $namemoyens qu'il ont besoin d'être remplacer par la valeur de la variable name, vous pouvez aussi effectuer certaines opérations dans l'interpolation, par exemples"Hello ${name.toUpperCase}, it's $weather today!"
Londo
3

Voici une liste de ce que vous String.formatpouvez faire. Il en va de mêmeprintf

int i = 123;
o.printf( "|%d|%d|%n" ,       i, -i );      // |123|-123|
o.printf( "|%5d|%5d|%n" ,     i, -i );      // |  123| –123|
o.printf( "|%-5d|%-5d|%n" ,   i, -i );      // |123  |-123 |
o.printf( "|%+-5d|%+-5d|%n" , i, -i );      // |+123 |-123 |
o.printf( "|%05d|%05d|%n%n",  i, -i );      // |00123|-0123|

o.printf( "|%X|%x|%n", 0xabc, 0xabc );      // |ABC|abc|
o.printf( "|%04x|%#x|%n%n", 0xabc, 0xabc ); // |0abc|0xabc|

double d = 12345.678;
o.printf( "|%f|%f|%n" ,         d, -d );    // |12345,678000|     |-12345,678000|
o.printf( "|%+f|%+f|%n" ,       d, -d );    // |+12345,678000| |-12345,678000|
o.printf( "|% f|% f|%n" ,       d, -d );    // | 12345,678000| |-12345,678000|
o.printf( "|%.2f|%.2f|%n" ,     d, -d );    // |12345,68| |-12345,68|
o.printf( "|%,.2f|%,.2f|%n" ,   d, -d );    // |12.345,68| |-12.345,68|
o.printf( "|%.2f|%(.2f|%n",     d, -d );    // |12345,68| |(12345,68)|
o.printf( "|%10.2f|%10.2f|%n" , d, -d );    // |  12345,68| | –12345,68|
o.printf( "|%010.2f|%010.2f|%n",d, -d );    // |0012345,68| |-012345,68|

String s = "Monsterbacke";
o.printf( "%n|%s|%n", s );                  // |Monsterbacke|
o.printf( "|%S|%n", s );                    // |MONSTERBACKE|
o.printf( "|%20s|%n", s );                  // |        Monsterbacke|
o.printf( "|%-20s|%n", s );                 // |Monsterbacke        |
o.printf( "|%7s|%n", s );                   // |Monsterbacke|
o.printf( "|%.7s|%n", s );                  // |Monster|
o.printf( "|%20.7s|%n", s );                // |             Monster|

Date t = new Date();
o.printf( "%tT%n", t );                     // 11:01:39
o.printf( "%tD%n", t );                     // 04/18/08
o.printf( "%1$te. %1$tb%n", t );            // 18. Apr
PRO_gramista
la source
1

Bien que @Londo ait mentionné l'interpolateur de chaîne "s" de Scala, je pense que l' interpolateur de chaîne "f" de Scala est plus pertinent pour la question d'origine. L'exemple utilisé quelques fois dans d'autres réponses pourrait également être écrit (depuis Scala 2.10) de cette façon:

scala> val name = "Ivan"
name: String = Ivan
scala> val thing = "Scala"
thing: String = Scala
scala> val formatted = f"Hello $name%s, isn't $thing%s cool?"
formatted: String = Hello Ivan, isn't Scala cool?

Le lien avec la question d'origine est de savoir que:

  • formattedest défini par une chaîne précédée de la lettre "f". Il s'agit de l'interpolateur de chaîne "f" (formatage).
  • L'interpolateur de chaîne "f" utilise java.util.Formatter
  • java.lang.String.format utilise le même java.util.Formatter

La bonne chose à propos de l'interpolation de chaîne est qu'elle vous permet de voir quelle variable est substituée directement dans la chaîne au lieu d'avoir à la faire correspondre avec les arguments de la String.formatméthode.

Reid Spencer
la source
0

En scala, pour l'interpolation de chaîne, nous avons $ qui sauve la journée et nous facilite la vie:

Par exemple: Vous voulez définir une fonction qui prend le nom et l'âge d'entrée et dit Bonjour avec le nom et dit son âge. Cela peut être écrit comme ceci:

def funcStringInterpolationDemo(name:String,age:Int)=s"Hey ! my name is $name and my age is $age"

Par conséquent, lorsque vous appelez cette fonction: comme ceci:

funcStringInterpolationDemo("Shivansh",22)

Sa sortie serait:

Hey ! my name is Shivansh and my age is 22

Vous pouvez écrire le code pour le changer dans la même ligne, comme si vous voulez ajouter 10 ans à l'âge!

alors la fonction pourrait être:

def funcStringInterpolationDemo(name:String,age:Int)=s"Hey ! my name is $name and my age is ${age+10}"

Et maintenant, la sortie serait:

Hey ! my name is Shivansh and my age is 32
Shiv4nsh
la source