¿Cómo usar java.String.format en Scala?

322

Estoy tratando de usar un .formatmétodo de una cadena. Pero si coloco% 1,% 2, etc. en la cadena, se arroja java.util.UnknownFormatConversionException apuntando a una pieza de código fuente Java confusa:

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

De esto entiendo que el %carbón está prohibido. Si es así, ¿qué debo usar para los marcadores de posición de argumento?

Yo uso Scala 2.8.

Ivan
fuente

Respuestas:

302

Si bien todas las respuestas anteriores son correctas, todas están en Java. Aquí hay un ejemplo de Scala:

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

También tengo una publicación de blog sobre cómo hacer formatque el %operador de Python sea ​​útil.

pr1001
fuente
2
Muchos ejemplos en la documentación de JDK: docs.oracle.com/javase/7/docs/api/java/util/…
angelcervera
1
Puede simplificar aplicando formatdirectamente al literal de cadena:"Hello %s, isn't %s cool?".format("Ivan", "Scala")
sotrh
298

No necesita usar números para indicar el posicionamiento. Por defecto, la posición del argumento es simplemente el orden en que aparece en la cadena.

Aquí hay un ejemplo de la forma correcta de usar esto:

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

Siempre usará un %seguido de algunos otros caracteres para que el método sepa cómo debe mostrar la cadena. %ses probablemente el más común, y solo significa que el argumento debe tratarse como una cadena.

No enumeraré todas las opciones, pero daré algunos ejemplos solo para darle una 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.formatsolo usa a java.util.Formatter, así que para obtener una descripción completa de las opciones, puede ver los javadocs Formatter .

Y, como menciona BalusC, verá en la documentación que es posible cambiar el orden predeterminado de los argumentos si es necesario. Sin embargo, probablemente la única vez que necesite / desee hacer esto es si está utilizando el mismo argumento más de una vez.

TM.
fuente
127

En lugar de mirar el código fuente, debería leer la sintaxis de Javadoc String.format () y Formatter .

Usted especifica el formato del valor después del%. Por ejemplo, para entero decimal es d, y para String es s:

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

Salida:

Hello, world on line 20

Para hacer lo que ha intentado (utilizar un índice argumento), que utilice: *n*$,

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

Salida:

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

Puedes usar esto;

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

Salida:

abbc

Engin Ardıç
fuente
1
Nunca he visto este tipo de uso, es muy útil cuando repito cadena, ¡genial!
Domi.Zhang
8
+1 esto se parece más a lo que usas como desarrollador de C #. Allí, usamos {0}y en {1}lugar de %1$y %2$.
cenizas999
@ ashes999 Soy de c # land también. Estoy tan acostumbrado a los corchetes numerados que había olvidado que esa no era la forma estándar de hacer las cosas. ¡Sin embargo, ver los signos de porcentaje lo devuelve todo!
JonnyRaa
13

También tenga en cuenta que Scala extiende String con una serie de métodos (a través de la conversión implícita a una WrappedString introducida por Predef) para que también pueda hacer lo siguiente:

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

En Scala 2.10

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

s"Hello $name, it's $weather today!"
Londo
fuente
1
Supongo que esto es simplemente una sintaxis especial de concatenación de cadenas (lo que significa que $ name y $ weather son referencias duras a las variables definidas anteriormente). Sin embargo, String.Format toma la plantilla como parámetro y permite, por ejemplo, recuperar la plantilla de un archivo de propiedades y demás. - ¿Es eso posible con la sintaxis anterior?
chiccodoro
Se llama interpolación de cadenas, dentro de la escala hay dos tipos: s "" yf "", la 's' es una cadena simple y la 'f' es similar a la printf, incluso podría definir su propia interpolación (no he tratar). Esto $namesignifica que debe reemplazarse con el valor de la variable name, por ejemplo, también puede realizar operaciones en la interpolacións"Hello ${name.toUpperCase}, it's $weather today!"
Londo
3

Esta es una lista de lo que String.formatpuede hacer. Lo mismo va paraprintf

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

Aunque @Londo mencionó el interpolador de cadenas "s" de Scala, creo que el interpolador de cadenas "f" de Scala es más relevante para la pregunta original. El ejemplo utilizado algunas veces en otras respuestas también podría escribirse (desde Scala 2.10) de esta manera:

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 conexión con la pregunta original es tener en cuenta que:

  • formattedse define con una cadena que tiene el prefijo con la letra "f". Este es el interpolador de cadenas "f" (formateo).
  • El interpolador de cadenas "f" utiliza java.util.Formatter
  • java.lang.String.format usa lo mismo java.util.Formatter

Lo bueno de la interpolación de cadenas es que le permite ver qué variable se sustituye directamente en la cadena en lugar de tener que hacerla coincidir con los argumentos del String.formatmétodo.

Reid Spencer
fuente
0

En scala, para la interpolación de cadenas tenemos $ que ahorra el día y hace nuestra vida mucho más fácil:

Por ejemplo: Desea definir una función que tome el nombre y la edad de entrada y diga Hola con el nombre y diga su edad. Eso se puede escribir así:

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

Por lo tanto, cuando llamas a esta función: así:

funcStringInterpolationDemo("Shivansh",22)

Su salida sería:

Hey ! my name is Shivansh and my age is 22

¡Puede escribir el código para cambiarlo en la misma línea, como si quisiera agregar 10 años a la edad!

entonces la función podría ser:

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

Y ahora el resultado sería:

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