Come usare java.String.format in Scala?


322

Sto cercando di utilizzare un .formatmetodo di una stringa. Ma se inserisco% 1,% 2, ecc. Nella stringa, viene generato java.util.UnknownFormatConversionException che punta a un pezzo di codice sorgente Java confuso:

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

Da ciò capisco che il %carbone è proibito. In tal caso, cosa dovrei usare per i segnaposto degli argomenti?

Uso Scala 2.8.

Risposte:


302

Mentre tutte le risposte precedenti sono corrette, sono tutte in Java. Ecco un esempio di Scala:

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

Ho anche un post sul blog su come rendere formatl' %operatore di Python che potrebbe essere utile.


2
Molti esempi nella documentazione di JDK: docs.oracle.com/javase/7/docs/api/java/util/…
angelcervera

1
Puoi semplificare applicando formatdirettamente alla stringa letterale:"Hello %s, isn't %s cool?".format("Ivan", "Scala")
sotrh

298

Non è necessario utilizzare i numeri per indicare il posizionamento. Per impostazione predefinita, la posizione dell'argomento è semplicemente l'ordine in cui appare nella stringa.

Ecco un esempio del modo corretto di utilizzare questo:

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

Utilizzerai sempre un %seguito da altri caratteri per far sapere al metodo come dovrebbe visualizzare la stringa. %sè probabilmente il più comune e significa solo che l'argomento dovrebbe essere trattato come una stringa.

Non elencherò tutte le opzioni, ma fornirò alcuni esempi solo per darti un'idea:

// 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.formatusa solo un java.util.Formatter, quindi per una descrizione completa delle opzioni puoi vedere il Formatter javadocs .

E, come menziona BalusC, vedrai nella documentazione che è possibile modificare l'ordinamento degli argomenti predefinito, se necessario. Tuttavia, probabilmente l'unica volta che avresti bisogno / desideri farlo è se stai usando lo stesso argomento più di una volta.


127

Invece di guardare il codice sorgente, dovresti leggere la sintassi javadoc String.format () e Formatter .

Si specifica il formato del valore dopo%. Ad esempio per intero decimale è d, e per String è s:

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

Produzione:

Hello, world on line 20

Per fare ciò si è tentato (utilizzare un indice argomento), si usa: *n*$,

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

Produzione:

Line:20. Value:world. Result: Hello world at line 20

70

Puoi usare questo;

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

Produzione:

abbc


1
Non ho mai visto questo tipo di utilizzo, è molto utile quando si ripete la stringa, fantastico!
Domi.Zhang,

8
+1 è più simile a quello che usi come sviluppatore C #. Lì, usiamo {0}e {1}invece di %1$e %2$.
ashes999,

@ ashes999 Vengo anch'io dalla terra c #. Sono così abituato alle parentesi numerate che avevo dimenticato che non era il modo standard di fare le cose. Vedere i segni di percentuale riporta però tutto indietro!
JonnyRaa,

13

Si noti inoltre che Scala estende String con una serie di metodi (tramite conversione implicita in una WrappedString introdotta da Predef) in modo da poter effettuare le seguenti operazioni:

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


10

In Scala 2.10

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

s"Hello $name, it's $weather today!"

1
Suppongo che questa sia semplicemente una sintassi speciale della concatenazione di stringhe (il che significa che $ name e $ weather sono riferimenti concreti alle variabili definite in precedenza). String.Format utilizza tuttavia il modello come parametro e consente quindi ad esempio di recuperare il modello da un file delle proprietà e simili. - È possibile con la sintassi sopra?
Chiccodoro,

Si chiama interpolazione String, all'interno di Scala ci sono due tipi: s "" e f "", la 's' è una stringa semplice e la 'f' è simile alla printf, potresti persino definire la tua interpolazione (non ho provare). Ciò $namesignifica che deve essere sostituito con il valore della variabile name, potresti anche fare un'operazione nell'interpolazione, ad esempios"Hello ${name.toUpperCase}, it's $weather today!"
Londo

3

Questa è una lista di cosa String.formatpuò fare. Lo stesso vale perprintf

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


1

Sebbene @Londo abbia menzionato l'interpolatore di stringhe "s" di Scala, penso che l' interpolatore di stringhe "f" di Scala sia più pertinente alla domanda originale. L'esempio usato qualche volta in altre risposte potrebbe anche essere scritto (dalla Scala 2.10) in questo modo:

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?

La connessione alla domanda originale deve essere consapevole che:

  • formattedè definito con una stringa che ha il prefisso con la lettera "f". Questo è l'interpolatore di stringhe "f" (formattazione).
  • L'interpolatore di stringhe "f" utilizza java.util.Formatter
  • java.lang.String.format usa lo stesso java.util.Formatter

La cosa bella dell'interpolazione di stringhe è che ti permette di vedere quale variabile viene sostituita direttamente nella stringa invece di doverla abbinare con gli argomenti al String.formatmetodo.


0

In scala, per l'Interpolazione di stringhe abbiamo $ che salva la giornata e semplifica la vita:

Per esempio: vuoi definire una funzione che prende il nome e l'età dell'input e dice Hello With the name e dice la sua età. Questo può essere scritto in questo modo:

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

Quindi, quando chiami questa funzione: in questo modo:

funcStringInterpolationDemo("Shivansh",22)

Il suo output sarebbe:

Hey ! my name is Shivansh and my age is 22

Puoi scrivere il codice per cambiarlo nella stessa riga, come se volessi aggiungere 10 anni all'età!

quindi la funzione potrebbe essere:

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

E ora l'output sarebbe:

Hey ! my name is Shivansh and my age is 32
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.