Jak korzystać z java.String.format w Scali?


322

Próbuję użyć .formatmetody ciągu. Ale jeśli umieszczę% 1,% 2 itd. W ciągu, zostanie wygenerowany wyjątek java.util.UnknownFormatConversionException wskazujący na mylący fragment kodu źródłowego Java:

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

Z tego rozumiem, że %char jest zabronione. Jeśli tak, to czego powinienem użyć dla symboli zastępczych argumentów?

Używam Scali 2.8.

Odpowiedzi:


302

Chociaż wszystkie poprzednie odpowiedzi są poprawne, wszystkie są w Javie. Oto przykład Scali:

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

Mam też wpis na blogu o tworzeniuformat% przydatnego operatora np. Pythona .


2
Wiele przykładów w dokumentacji JDK: docs.oracle.com/javase/7/docs/api/java/util/…
angelcervera

1
Możesz uprościć, stosując formatbezpośrednio do literału łańcuchowego:"Hello %s, isn't %s cool?".format("Ivan", "Scala")
sotrh

298

Nie musisz używać liczb do wskazywania pozycji. Domyślnie pozycja argumentu jest po prostu kolejnością, w jakiej występuje w ciągu.

Oto przykład właściwego sposobu użycia tego:

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

Zawsze użyjesz %następujących po nich innych znaków, aby poinformować metodę, jak powinien wyświetlać ciąg. %sjest prawdopodobnie najczęstszy i oznacza po prostu, że argument należy traktować jako ciąg znaków.

Nie wymienię wszystkich opcji, ale podam kilka przykładów, aby dać ci pomysł:

// 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.formatużywa po prostu java.util.Formatter, więc dla pełnego opisu opcji możesz zobaczyć javadocs Formatera .

Jak wspomina BalusC, w dokumentacji zobaczysz, że w razie potrzeby możesz zmienić domyślną kolejność argumentów. Prawdopodobnie jednak jedyny raz potrzebujesz / chcesz to zrobić, jeśli używasz tego samego argumentu więcej niż jeden raz.


127

Zamiast patrzeć na kod źródłowy, powinieneś przeczytać javadoc String.format () i składnię Formatera .

Format wartości określa się po%. Na przykład dla dziesiętnej liczby całkowitej d, a dla String jest to s:

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

Wynik:

Hello, world on line 20

Aby zrobić to, czego próbowałem (użyć indeksu argument), możesz użyć: *n*$,

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

Wynik:

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

70

Możesz tego użyć;

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

Wynik:

abbc


1
Nigdy nie widziałem takiego zastosowania, jest to bardzo przydatne, gdy powtórz ciąg znaków, świetnie!
Domi.Zhang

8
+1 to bardziej przypomina to, czego używasz jako programisty C #. Tam używamy {0}i {1}zamiast %1$i %2$.
ashes999

@ ashes999 Jestem z c # land aswell. Jestem tak przyzwyczajony do numerowanych nawiasów, że zapomniałem, że to nie był standardowy sposób robienia rzeczy. Widząc znaki procentu, wszystko to wraca!
JonnyRaa

13

Zauważ też, że Scala rozszerza String na wiele metod (poprzez niejawną konwersję na WrappedString przyniesioną przez Predef), więc możesz również wykonać następujące czynności:

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


10

W Scali 2.10

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

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

1
Rozumiem, że jest to jedynie specjalna składnia łączenia łańcuchów (co oznacza, że ​​$ name i $ weather są twardymi odniesieniami do zmiennych zdefiniowanych wcześniej). String.Format przyjmuje jednak szablon jako parametr, dzięki czemu można na przykład pobrać szablon z pliku właściwości i tym podobne. - Czy jest to możliwe przy powyższej składni?
chiccodoro,

Nazywa się interpolacją ciągów, w scali istnieją dwa typy: s „” i f ””, „s” jest prostym ciągiem, a „f” jest podobny do printf, można nawet zdefiniować własną interpolację (ja nie próbować). Te $nameśrodki, które to muszą być zastąpić wartości zmiennej name, można również wykonać operację w interpolacji, na przykłads"Hello ${name.toUpperCase}, it's $weather today!"
Londo

3

To jest lista tego, co String.formatmożna zrobić. To samo dotyczyprintf

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

Chociaż @Londo wspomniało o interpolatorze ciągów „Scala Scali, myślę, że interpolator ciągów „Scala Scali jest bardziej odpowiedni do pierwotnego pytania. Przykład wykorzystany kilka razy w innych odpowiedziach można również napisać (od Scali 2.10) w ten sposób:

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?

W związku z pierwotnym pytaniem należy pamiętać, że:

  • formattedjest zdefiniowany za pomocą ciągu znaków poprzedzonego literą „f”. To jest interpolator napisów „f” (formatowanie).
  • Używa interpolatora łańcuchowego „f” java.util.Formatter
  • java.lang.String.format używa tego samego java.util.Formatter

Zaletą interpolacji łańcuchów jest to, że pozwala zobaczyć, która zmienna jest podstawiana bezpośrednio w łańcuch, bez konieczności dopasowywania jej z argumentami do String.formatmetody.


0

W scala, na interpolację łańcuchów mamy $, który oszczędza dzień i ułatwia nam życie:

Na przykład: Chcesz zdefiniować funkcję, która pobiera nazwę wejściową i wiek oraz mówi „Cześć z nazwą” i „podaje wiek”. Można to napisać w ten sposób:

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

Dlatego po wywołaniu tej funkcji: tak:

funcStringInterpolationDemo("Shivansh",22)

Jego wyniki byłyby następujące:

Hey ! my name is Shivansh and my age is 22

Możesz napisać kod, aby zmienić go w tym samym wierszu, na przykład, jeśli chcesz dodać 10 lat do wieku!

funkcja może być:

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

A teraz wynik będzie:

Hey ! my name is Shivansh and my age is 32
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.