【问题标题】:Any way to skip a formatter token when using String.format()?使用 String.format() 时有什么方法可以跳过格式化程序令牌?
【发布时间】:2015-02-10 16:43:49
【问题描述】:

我有一个String myString = "%d New Voicemail";

我想为 2 做这个:

String myString = "%d New Voicemail";
System.out.println(String.format(myString, 2));

输出:2 条新语音邮件


我想这样做 5:

String myString = "%d New Voicemail";
System.out.println(String.format(myString, 5));

输出:5 条新语音邮件


我想为 1 做这个:

String myString = "%d New Voicemail";
System.out.println(String.format(myString));

输出:崩溃

预期输出:新语音邮件


如您所见,对于“1”,我只想显示字符串而不进行格式化。如果我只是省略了额外的参数,它就会崩溃。有我不知道的简单解决方案吗?

我可以这样做,但想知道是否有更简单的方法:

int num;
if (num == 1){
    System.out.println(myString.subString(3));

} else {
    System.out.println(String.format(myString, num));

}

【问题讨论】:

  • 当然你可以用System.out.printf()代替println。但这不会回答你的问题。
  • 如果只有一封新的语音邮件,为什么要省略 1?只显示“1 个新语音邮件”不是更容易(同时也是正确的)吗?除非是学术练习,否则看起来你正在努力解决一个不存在的问题。
  • @GiulioFranco 不是学术性的。这是设计团队想要的。不受我控制。我只是在尝试最好的实现方式。

标签: java string-formatting string.format


【解决方案1】:

试试

System.out.printf("%s New Voicemail%n", num == 1 ? "" : num);

【讨论】:

  • 你为什么不试试呢? :-) 当然它会编译,Java 会通过自动应用toString() 来处理它。 ?: 的类型由第一个操作数确定。类似于"1" + 1
  • 酷,我的评论没有任何意义,因为它回答的评论消失了。好吧。这是一种过度简化。嗯。
【解决方案2】:

当然,这是一种极端的技术。但是,一旦设置好,使用起来就很简单,设计团队也没有任何抱怨的理由。

static String voicemail( int n ){
    MessageFormat form = new MessageFormat("{0}");
    double[] filelimits = {0,1,2};
    String[] filepart = {"No New Voicemail",
             "New Voicemail",
             "{0,number} New Voicemails"};
    ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart);
    form.setFormatByArgumentIndex(0, fileform);
    Integer[] values = new Integer[]{n};
    return form.format( values );
}

测试:

for( int i = 0; i <=3; ++i ){
    System.out.println( voicemail(i) );
}

输出。

No New Voicemail
New Voicemail
2 New Voicemails
3 New Voicemails

【讨论】:

  • 是的,我需要能够使用硬编码的字符串和格式化程序的原因是出于本地化目的。在某些语言中,格式化程序出现在不同的位置。不过感谢答案。
  • 文件部分组件可以本地化。
  • 注明。我相信我会寻求一个更简单的解决方案。 +1 对于大多数人来说可能是最完整的答案。幸运的是,我不需要对单数和复数进行任何比较,这个练习的目标是重用我已经拥有的字符串,这样我们就不必发送新的字符串来进行本地化。再次感谢您的回答。
  • 这不是回答如何使用格式的问题!
【解决方案3】:

虽然传递给printf 的参数少于格式行预期的参数是不行的,但传递更多的参数是可以的。您可以对格式行本身使用条件表达式,如下所示:

System.out.printf(num != 1 ? myString : myString.substring(3), num);

Demo.

【讨论】:

  • 顺便说一句,这个解决方案和我自己发布的一样糟糕。在现实生活中,单数和复数应该有两个分开的字符串,以区分“1个新语音邮件”和“5个新语音邮件”。而对于 I18N,你甚至不应该假设两个版本就足够了。
  • @MichaelPiefel 当然 - 在 Stack Overflow 上发布的任何内容都应作为说明,而不是作为生产就绪代码。使这种语言不可知论将代码提升到另一个层次 - 现在不能假设“复数”对于所有大于 1 的数字都是相同的。例如,在俄语中,以 1 结尾的数字、以 2、3 或 4 结尾的数字以及以 5 及以上结尾的数字(包括零,但不包括“...teen”数字)的字符串会有所不同。跨度>
  • @MichaelPiefel 尽管人们试图将其包括在内,但正如问题所述,我不需要区分单数与复数。所以在这种情况下,这个答案是正确的。我选择此作为最佳答案,因为您确实回答了“传递更少的参数是不行的......”这一事实。
  • 当然,如果您的意图不是更改原始字符串,那么此答案将缺少换行符。
【解决方案4】:

由于您想要使用两个不同的指令来打印 1 或 >1 封语音邮件,很明显您必须在您的程序中的某处有一个if。您可以在此处更改格式。

String format = "New Voicemail";
if (num == 1){
  System.out.println(myString);
} else {
  System.out.println(String.format("%d " + format, 5));
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-20
    • 2021-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多