Wie verwende ich java.String.format in Scala?

322

Ich versuche, eine .formatMethode eines Strings zu verwenden. Wenn ich jedoch% 1,% 2 usw. in die Zeichenfolge einfüge, wird java.util.UnknownFormatConversionException ausgelöst, die auf ein verwirrendes Java-Quellcodeteil verweist:

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));
    }
}

Daraus verstehe ich, dass %Saibling verboten ist. Wenn ja, was soll ich dann für Argumentplatzhalter verwenden?

Ich benutze Scala 2.8.

Ivan
quelle

Antworten:

302

Alle vorherigen Antworten sind korrekt, aber alle in Java. Hier ist ein Scala-Beispiel:

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

Ich habe auch einen Blog-Beitrag darüber , formatwie man Pythons %Operator macht , der nützlich sein könnte.

pr1001
quelle
2
Viele Beispiele in der JDK-Dokumentation: docs.oracle.com/javase/7/docs/api/java/util/…
angelcervera
1
Sie können vereinfachen, indem Sie formatdirekt auf das Zeichenfolgenliteral anwenden :"Hello %s, isn't %s cool?".format("Ivan", "Scala")
sotrh
298

Sie müssen keine Zahlen verwenden, um die Positionierung anzuzeigen. Standardmäßig ist die Position des Arguments einfach die Reihenfolge, in der es in der Zeichenfolge angezeigt wird.

Hier ist ein Beispiel für die richtige Verwendung:

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

Sie werden immer ein %gefolgt von einigen anderen Zeichen verwenden, um der Methode mitzuteilen, wie die Zeichenfolge angezeigt werden soll. %sist wahrscheinlich die häufigste und bedeutet nur, dass das Argument als Zeichenfolge behandelt werden sollte.

Ich werde nicht jede Option auflisten, aber ich werde ein paar Beispiele geben, um Ihnen eine Idee zu geben:

// 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.formatverwendet nur a java.util.Formatter, sodass Sie für eine vollständige Beschreibung der Optionen die Formatter-Javadocs sehen können .

Und wie BalusC erwähnt, sehen Sie in der Dokumentation, dass Sie die Standardargumentreihenfolge bei Bedarf ändern können. Wahrscheinlich müssen / möchten Sie dies jedoch nur tun, wenn Sie dasselbe Argument mehrmals verwenden.

TM.
quelle
127

Anstatt den Quellcode zu betrachten, sollten Sie die Syntax javadoc String.format () und Formatter lesen .

Sie geben das Format des Werts nach% an. Zum Beispiel für eine dezimale Ganzzahl dund für einen String s:

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

Ausgabe:

Hello, world on line 20

Um das zu tun, was Sie versucht haben (verwenden Sie einen Argumentindex), verwenden Sie : *n*$,

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

Ausgabe:

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

Sie können dies verwenden;

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

Ausgabe:

abbc

Engin Ardıç
quelle
1
Ich habe diese Art der Verwendung noch nie gesehen, es ist sehr nützlich, wenn man die Saite wiederholt, großartig!
Domi.Zhang
8
+1 Dies entspricht eher dem, was Sie als C # -Entwickler verwenden. Dort verwenden wir {0}und {1}anstelle von %1$und %2$.
Asche999
@ ashes999 Ich komme auch aus C # Land. Ich bin so an nummerierte Klammern gewöhnt, dass ich vergessen hätte, dass dies nicht die Standardmethode ist. Das Sehen der Prozentzeichen bringt jedoch alles zurück!
JonnyRaa
13

Beachten Sie auch, dass Scala String mit einer Reihe von Methoden erweitert (durch implizite Konvertierung in einen von Predef eingebrachten WrappedString), sodass Sie auch Folgendes tun können:

val formattedString = "Hello %s, isn't %s cool?".format("Ivan", "Scala")
Denis Phillips
quelle
11

Die offizielle Referenz ist die Klasse Formatter.

Alberto Segura
quelle
10

In Scala 2.10

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

s"Hello $name, it's $weather today!"
Londo
quelle
1
Ich gehe davon aus, dass dies lediglich eine spezielle Syntax für die Verkettung von Zeichenfolgen ist (was bedeutet, dass $ name und $ weather harte Verweise auf die zuvor definierten Variablen sind). String.Format nimmt jedoch die Vorlage als Parameter und ermöglicht so beispielsweise das Abrufen der Vorlage aus einer Eigenschaftendatei und dergleichen. - Ist das mit der obigen Syntax möglich?
Chiccodoro
Es heißt String-Interpolation, innerhalb von Scala gibt es zwei Typen: s "" und f "", das 's' ist ein einfacher String und das 'f' ähnelt dem printf, Sie könnten sogar Ihre eigene Interpolation definieren (ich habe nicht Versuchen). Das $namebedeutet, dass es durch den Wert der Variablen ersetzt werden muss name, Sie könnten auch Operation in der Interpolation ausführen, zum Beispiels"Hello ${name.toUpperCase}, it's $weather today!"
Londo
3

Dies ist eine Liste der Möglichkeiten String.format. Das gleiche gilt fürprintf

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
quelle
1

Obwohl @Londo Scalas "s" -Stringinterpolator erwähnte, denke ich, dass Scalas "f" -Stringinterpolator für die ursprüngliche Frage relevanter ist. Das Beispiel, das einige Male in anderen Antworten verwendet wurde, könnte auch (seit Scala 2.10) folgendermaßen geschrieben werden:

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?

Die Verbindung zur ursprünglichen Frage ist zu beachten, dass:

  • formattedwird mit einer Zeichenfolge definiert, der der Buchstabe "f" vorangestellt ist. Dies ist der String-Interpolator "f" (Formatierung).
  • Der String-Interpolator "f" verwendet java.util.Formatter
  • java.lang.String.format verwendet das gleiche java.util.Formatter

Das Schöne an der String-Interpolation ist, dass Sie sehen können, welche Variable direkt in den String eingefügt wird, anstatt sie mit den Argumenten der String.formatMethode abgleichen zu müssen .

Reid Spencer
quelle
0

In Scala haben wir für die String-Interpolation $ , das den Tag rettet und unser Leben viel einfacher macht:

Zum Beispiel: Sie möchten eine Funktion definieren, die den Eingabenamen und das Alter übernimmt und Hallo sagt. Mit dem Namen und dem Alter. Das kann so geschrieben werden:

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

Wenn Sie diese Funktion aufrufen: So:

funcStringInterpolationDemo("Shivansh",22)

Seine Ausgabe wäre:

Hey ! my name is Shivansh and my age is 22

Sie können den Code schreiben, um ihn in derselben Zeile zu ändern, beispielsweise wenn Sie dem Alter 10 Jahre hinzufügen möchten!

dann könnte die Funktion sein:

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

Und jetzt wäre die Ausgabe:

Hey ! my name is Shivansh and my age is 32
Shiv4nsh
quelle