如何在Scala中使用java.String.format?


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

从中我了解到%char是被禁止的。如果是这样,那么我应该对参数占位符使用什么?

我使用Scala 2.8。

Answers:


302

尽管所有先前的回答都是正确的,但它们都是Java语言。这是一个Scala示例:

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

我也有一篇博客文章,关于编写format类似Python的%运算符可能很有用。



1
您可以通过format直接应用于字符串文字来简化操作:"Hello %s, isn't %s cool?".format("Ivan", "Scala")
sotrh 2014年

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,因此有关选项的完整说明,请参见Formatter javadocs

而且,正如BalusC所述,您将在文档中看到可以根据需要更改默认参数的顺序。但是,可能唯一需要这样做的时间是,如果您多次使用同一参数。


127

而不是查看源代码,您应该阅读javadoc String.format()Formatter语法

您可以在%后面指定值的格式。例如,对于十进制整数为d,对于字符串为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");

输出:

阿比克


1
我从未见过这种用法,当重复字符串时非常有用!
Domi.Zhang

8
+1就像您用作C#开发人员一样。在这里,我们使用{0}and {1}代替%1$and %2$
ashes999

@ ashes999我也是c#的人。我已经习惯了忘掉编号,这不是标准的处理方式。看到百分号会使一切恢复原状!
JonnyRaa 2014年

13

还要注意,Scala使用多种方法扩展String(通过隐式转换为Predef引入的WrappedString),因此您还可以执行以下操作:

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


10

在Scala 2.10中

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

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

1
我认为这只是字符串连接的一种特殊语法(意味着$ name和$ weather是对之前定义的变量的硬引用)。但是,String.Format将模板作为参数,因此例如可以从属性文件等检索模板。-使用上述语法可能吗?
chiccodoro

这就是所谓的字符串插值,在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提到了Scala的“ s”字符串内插器,但我认为Scala的“ f”字符串内插器与原始问题更相关。该示例在其他响应中使用了几次,也可以这样编写(自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

在scala中,对于字符串Interpolation,我们可以使用$节省一天的时间,并使我们的生活更加轻松:

例如:您想定义一个函数,该函数接受输入名称和年龄,并用名称说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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.