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.