Як використовувати java.String.format у Scala?


322

Я намагаюся використовувати .format метод рядка. Але якщо я розміщую% 1,% 2 тощо у рядку, java.util.UnknownFormatConversionException викидається, вказуючи на заплутану частину вихідного коду 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));
    }
}

З цього я це розумію % заборонено заборонено. Якщо так, то що мені слід використовувати для заповнювачів аргументів?

Я використовую Scala 2.8.

Відповіді:


302

Хоча всі попередні відповіді правильні, вони всі на Java. Ось приклад Scala:

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

У мене також є повідомлення в блозі про те, formatяк зробити %оператора Python, який може бути корисним.


2
Дуже багато прикладів у документації JDK: docs.oracle.com/javase/7/docs/api/java/util/…
angelcervera

1
Можна спростити, застосувавши formatбезпосередньо до літерального рядка:"Hello %s, isn't %s cool?".format("Ivan", "Scala")
sotrh

298

Не потрібно використовувати цифри для позначення позиціонування. За замовчуванням позиція аргументу - це просто порядок, в якому він відображається в рядку.

Ось приклад правильного способу використання цього:

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

Ви завжди будете використовувати %наступні інші символи, щоб метод знав, як він повинен відображати рядок. %sце, мабуть, найпоширеніший, і це просто означає, що аргумент слід розглядати як рядок.

Я не буду перераховувати кожен варіант, але я наведу кілька прикладів, щоб дати вам уявлення:

// 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.formatпросто використовує a java.util.Formatter, тому для повного опису параметрів ви можете побачити формат javadocs .

І, як згадує BalusC, ви побачите в документації, що можна змінити впорядкування аргументів за замовчуванням, якщо потрібно. Однак, мабуть, єдиний раз, коли вам знадобиться / хочете це зробити, якщо ви використовуєте один і той же аргумент не один раз.


127

Замість того, щоб дивитись на вихідний код, слід прочитати синтаксис javadoc String.format () та Formatter .

Ви визначаєте формат значення після%. Наприклад, для десяткового цілого числа воно є d, а для String це s:

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

Вихід:

Hello, world on line 20

Для того, щоб робити те , що ви пробували (використовувати індекс аргументу), можна використовувати: *n*$,

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

Вихід:

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

70

Ви можете використовувати це;

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

Вихід:

abbc


1
Я ніколи не бачив подібного роду використання, це дуже корисно, коли повторюється рядок, чудово!
Домі.Жанг

8
+1 це більше нагадує те, що ви використовуєте як розробник C #. Там ми використовуємо {0}і {1}замість %1$і %2$.
ashes999

@ ashes999 Я також із c # land. Я так звик до нумерованих дужок, що я забув, що це був не стандартний спосіб робити. Побачення знаків відсотків повертає все це назад!
JonnyRaa

13

Також зауважте, що Scala розширює String за допомогою ряду методів (шляхом неявного перетворення у WrappedString, запровадженого Predef), так що ви також можете зробити наступне:

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


10

У Скалі 2.10

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

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

1
Я вважаю, що це лише спеціальний синтаксис конкатенації рядків (мається на увазі, що $ name та $ weather є жорсткими посиланнями на визначені раніше змінні). String.Format, однак, приймає шаблон як параметр і, таким чином, дає можливість, наприклад, витягнути шаблон із файлу властивостей тощо. - Це можливо з вищевказаним синтаксисом?
чікодоро

Це виклик інтерполяції String, всередині scala є два типи: s "" і f "", "s" - це проста рядок, а "f" подібна до printf, ви навіть можете визначити власну інтерполяцію (у мене немає спробуйте). Це $nameозначає, що його потрібно замінити значенням змінної name, ви також можете зробити операцію в інтерполяції, наприкладs"Hello ${name.toUpperCase}, it's $weather today!"
Londo

3

Це перелік того, що String.formatможна зробити. Те ж саме стосуєтьсяprintf

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

Хоча @Londo згадується «S» рядок Інтерпол Scala, я думаю , що в Scala «е» рядок Интерполятор більш безпосереднє відношення до початкового питання. Приклад, використаний кілька разів в інших відповідях, також можна було написати (оскільки Scala 2.10) таким чином:

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?

Підключення до вихідного питання полягає в тому, щоб:

  • formattedвизначається рядком, який має префікс буквою "f". Це інтерполятор рядків "f" (форматування).
  • Інтерполятор рядків "f" використовує java.util.Formatter
  • java.lang.String.format використовує те саме java.util.Formatter

Приємна річ інтерполяції рядків полягає в тому, що вона дозволяє вам бачити, яка змінна підміняється безпосередньо в рядок, замість того, щоб відповідати її аргументам String.formatметоду.


0

Скажемо, для рядкової інтерполяції у нас є $, що економить день і полегшує наше життя:

Наприклад: Ви хочете визначити функцію, яка приймає ім'я та вік введення та каже ім'я Hello з ім'ям та каже його вік. Це можна записати так:

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

Отже, коли ви викликаєте цю функцію:

funcStringInterpolationDemo("Shivansh",22)

Його вихід буде:

Hey ! my name is Shivansh and my age is 22

Ви можете написати код, щоб змінити його в тому ж рядку, як, наприклад, якщо ви хочете додати 10 років до віку!

тоді функція може бути:

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

А тепер вихід буде:

Hey ! my name is Shivansh and my age is 32
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.