Como usar o java.String.format no Scala?


322

Estou tentando usar um .formatmétodo de uma seqüência de caracteres. Mas se eu colocar% 1,% 2, etc. na cadeia de caracteres, java.util.UnknownFormatConversionException será lançado apontando para um pedaço de código-fonte 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));
    }
}

Por isso eu entendo que %char é proibido. Nesse caso, o que devo usar para espaços reservados para argumentos?

Eu uso o Scala 2.8.

Respostas:


302

Embora todas as respostas anteriores estejam corretas, elas estão todas em Java. Aqui está um exemplo do Scala:

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

Eu também tenho um post sobre como fazer formatcomo %operador do Python que pode ser útil.


2
Um monte de exemplos na documentação JDK: docs.oracle.com/javase/7/docs/api/java/util/...
angelcervera

1
Você pode simplificar aplicando formatdiretamente à string literal:"Hello %s, isn't %s cool?".format("Ivan", "Scala")
sotrh 26/08/14

298

Você não precisa usar números para indicar o posicionamento. Por padrão, a posição do argumento é simplesmente a ordem em que ele aparece na string.

Aqui está um exemplo da maneira correta de usar isso:

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

Você sempre usará um %seguido por outros caracteres para permitir que o método saiba como deve exibir a sequência. %sé provavelmente o mais comum e significa apenas que o argumento deve ser tratado como uma string.

Não listarei todas as opções, mas darei alguns exemplos apenas para lhe dar uma idéia:

// 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.formatapenas usa a java.util.Formatter, portanto, para obter uma descrição completa das opções, você pode ver os javadocs do Formatador .

E, como o BalusC menciona, você verá na documentação que é possível alterar a ordem dos argumentos padrão, se necessário. No entanto, provavelmente a única vez que você precisará / deseja fazer isso é se estiver usando o mesmo argumento mais de uma vez.


127

Em vez de observar o código fonte, você deve ler a sintaxe javadoc String.format () e Formatter .

Você especifica o formato do valor após o%. Por exemplo, para número inteiro decimal, é d, e para String, é s:

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

Resultado:

Hello, world on line 20

Para fazer o que você tentou (usar um índice argumento), você usa: *n*$,

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

Resultado:

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

70

Você pode usar isso;

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

Resultado:

abbc


1
Eu nunca vi esse tipo de uso, é muito útil quando repetir uma string, ótimo!
precisa saber é o seguinte

8
+1 é mais parecido com o que você usa como desenvolvedor de C #. Lá, usamos {0}e em {1}vez de %1$e %2$.
ashes999

@ ashes999 Eu sou de c # land também. Estou tão acostumado com colchetes numerados que esqueci que não era a maneira padrão de fazer as coisas. Ver os sinais de porcentagem traz tudo de volta!
9134 JonnyRaa #

13

Observe também que o Scala estende String com vários métodos (via conversão implícita em um WrappedString trazido pelo Predef) para que você também possa fazer o seguinte:

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


10

No Scala 2.10

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

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

1
Entendo que essa é apenas uma sintaxe especial da concatenação de strings (o que significa que $ name e $ weather são referências concretas às variáveis ​​definidas anteriormente). String.Format, no entanto, leva o modelo como parâmetro e, portanto, possibilita, por exemplo, recuperar o modelo de um arquivo de propriedades e tal. - Isso é possível com a sintaxe acima?
Chiccodoro

É chamada interpolação de String, dentro do scala existem dois tipos: s "" ef "", o 's' é uma string simples e o 'f' é semelhante ao printf, você pode até definir sua própria interpolação (eu não experimentar). Os $namemeios que precisam ser substituir com o valor da variável name, você também pode fazer a operação na interpolação, por exemplos"Hello ${name.toUpperCase}, it's $weather today!"
Londo

3

Esta é uma lista do que String.formatpode fazer. O mesmo vale 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


1

Embora @Londo tenha mencionado o interpolador de cordas "s" de Scala, acho que o interpolador de cordas "f" de Scala é mais relevante para a pergunta original. O exemplo usado algumas vezes em outras respostas também pode ser escrito (desde o Scala 2.10) desta maneira:

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?

A conexão com a pergunta original é estar ciente de que:

  • formattedé definido com uma sequência prefixada com a letra "f". Este é o interpolador de seqüência de caracteres "f" (formatação).
  • O interpolador de string "f" usa java.util.Formatter
  • java.lang.String.format usa o mesmo java.util.Formatter

O bom da interpolação de cadeias de caracteres é que ela permite ver qual variável está sendo substituída diretamente na cadeia de caracteres, em vez de precisar correspondê-la aos argumentos do String.formatmétodo.


0

Em scala, para a Interpolação de cordas, temos $ que salvam o dia e tornam nossa vida muito mais fácil:

Por exemplo: você deseja definir uma função que aceite o nome e a idade da entrada e diga Olá com o nome e diga a idade. Isso pode ser escrito assim:

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

Portanto, quando você chama esta função: assim:

funcStringInterpolationDemo("Shivansh",22)

Sua saída seria:

Hey ! my name is Shivansh and my age is 22

Você pode escrever o código para alterá-lo na mesma linha, como se quiser adicionar 10 anos à idade!

então a função pode ser:

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

E agora a saída seria:

Hey ! my name is Shivansh and my age is 32
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.