足够了。这是这个问题的一个破烂致富。该模式非常简单,它接受一个
String
输入,验证它是否为数字,如果是数字,则将其转换为SHOUTY_SNAKE_CASE。 br /> 这很简单,但这也是我第一次使用Java 8的流,因此我想对我的(简单)用法发表意见。
private static final String[] words =
new String[]{"zero","one","two","three","four","five","six","seven","eight","nine"};
public static String convertNumbersToWords(final String input) {
if(input == null || !input.matches("^\d*$")){
throw new IllegalArgumentException("input cannot be null or non-numerical.");
}
return input.chars()
.mapToObj(c -> getWordFromCharCode(c).toUpperCase())
.collect(Collectors.joining("_"));
}
private static String getWordFromCharCode(int code){
return words[code - 48];
}
#1 楼
由于您需要一组与数字对齐的LOUD_WORDS
枚举集,最好是某种形式的数字索引...因此,用enum
代替String[]
似乎是完美的选择: />(我想您可以找出推导的结果。)性能方面。由于您还尝试了Java 8的某些功能,因此您可能还想考虑使用
Word.values()
来消除Optional
-validation:enum Word {
ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE;
}
如果您希望将
if
用作NullPointerException
的值,则可以坚持使用null
。评论
\ $ \ begingroup \ $
您如何建议从数字映射到字符串?每个通话是否都使用Word.values()[digit]?
\ $ \ endgroup \ $
–西蒙·福斯伯格
15年11月27日在21:47
\ $ \ begingroup \ $
@SimonForsberg是的.map(i-> Character.getNumericValue(i))。mapToObj(i-> Word.values()[i] .toString())...
\ $ \ endgroup \ $
– h.j.k.
15年11月28日在3:12
\ $ \ begingroup \ $
@ h.j.k。 Word.values()每次都会创建一个新数组。一次将所有值存储在一个数组中对我来说听起来更好,这并不像您将创建一个Word w = Word.THREE;。或任何东西。听起来像String []对我来说更好。
\ $ \ endgroup \ $
–西蒙·福斯伯格
15年11月28日在10:13
\ $ \ begingroup \ $
使用枚举表示实际输出值时会有些警惕。例如,如果您曾经希望支持其他非拉丁字符的语言,则可能会引起问题。使用String [](甚至是Map
\ $ \ endgroup \ $
–鲍勃
2015年11月29日0:36
#2 楼
为什么将它们存储为小写字母,仅在它们上调用toUpperCase
?以您打算使用它们的形式存储它们,并为每个单词保存一个函数调用。将字符串以相同的方式存储也将更容易理解。
#3 楼
我建议用code - 48
代替有点低级的Character.getNumericValue
。另一个考虑因素可能是使用guava的
CharMatcher.DIGIT.matchesAllOf
而不是使用regex来验证输入字符串,尽管我意识到使用库通常不是重点。 请注意,此方法也会为您传递数字值也大于9的数字(即罗马数字50),您必须考虑一种支持它们的方法。 (拆分为个位数?)
评论
\ $ \ begingroup \ $
建议图书馆是一个好主意! :)只是您需要谨慎,不要将整个评估集中在使用外部库上。但是您的回答很好,谢谢! :)
\ $ \ endgroup \ $
–IEatBagels
15年11月27日在15:40
\ $ \ begingroup \ $
可以将代码-48替换为代码-'0'吗? (这仍然不是完美的,但是更好的IMO)
\ $ \ endgroup \ $
– oliverpool
15年11月27日在16:31
\ $ \ begingroup \ $
@oliverpool:programmers.stackexchange.com/questions/303553/…:)
\ $ \ endgroup \ $
– Benjaminssp
15年11月27日在16:44
\ $ \ begingroup \ $
使用Character.isDigit进行过滤,使用Character.getNumericValue进行转换,然后再次过滤以限制为0-9的范围。
\ $ \ endgroup \ $
–大卫·康拉德(David Conrad)
15年11月27日在20:16
#4 楼
命名和方法分解让我们看一下该方法签名:
public static String convertNumbersToWords(final String input) {
方法名称建议转换数字...它适用于“ 1234”之类的输入。与数字类型相反,输入是字符串,并且“ 1234”是一个数字,而不是复数,这有点不自然。
此外,该方法还执行以下两项操作:
验证输入仅包含数字
将数字转换为
SHOUT_CASE
最好将其分解为两种方法,例如:
private static String convertValidatedDigitsToWords(final String digits) {
return digits.chars()
.mapToObj(ShoutySnake::getWordFromCharCode)
.collect(Collectors.joining("_"));
}
public static String convertDigitsToWords(final String input) {
if (input == null || !input.matches("\d*")) {
throw new IllegalArgumentException("input cannot be null or non-numerical.");
}
return convertValidatedDigitsToWords(input);
}
...,也许为数字输入添加重载:提示:
String.matches
表示^
和$
,无需在模式中包括它们。 >那么最好编译正则表达式。public static String convertDigitsToWords(final int number) {
if (number < 0) {
throw new IllegalArgumentException("input must be non-negative");
}
return convertValidatedDigitsToWords(Integer.toString(number));
}
幻数48
在此代码中,48是幻数:
private static final Pattern pattern = Pattern.compile("\d*");
public static String convertDigitsToWords(final String input) {
if (!pattern.matcher(input).matches()) {
throw new IllegalArgumentException("input must be non-null and non-negative.");
}
return convertValidatedDigitsToWords(input);
}
通过引用
'0'
,您可以轻松地降低其魔力: >评论
\ $ \ begingroup \ $
太好了,将它与@benjaminssp的建议结合起来以用Character.getNumericValue替换代码48,我想您已经找到答案了:
\ $ \ endgroup \ $
–user1477388
15年11月28日在18:16
\ $ \ begingroup \ $
感谢@ user1477388,您的评论促使我添加了另一部分;-)(魔术数字48)
\ $ \ endgroup \ $
– janos
15年11月28日在18:22
#5 楼
名称convertNumbersToWords()
不能清楚地反映该方法的作用。您可以使用convertNumbersToShoutySnakeCaseWords()
之类的Java约定来执行此操作,也可以使用与CONVERT_NUMBERS_TO_SHOUTY_SNAKE_CASE_WORDS()
之类的应用程序目的相匹配的方式来执行此操作评论
\ $ \ begingroup \ $
如果您将幽默感放在专业之上,那么也可以选择snakeShouts()
\ $ \ endgroup \ $
–亚伦
15年11月27日在15:02
\ $ \ begingroup \ $
仅仅因为代码是关于喧闹和蛇案的事情,并不意味着代码本身应该是喧闹的。
\ $ \ endgroup \ $
–西蒙·福斯伯格
15年11月27日在21:46
#6 楼
我建议更改尚未提及的三种想法。怎么办呢? />也一样。您是否真的要允许空输入?我建议不要。用*
替换+
:^[0-9]*$
我喜欢静态导入。它并不是每个人的最爱,但我认为,它使代码更具可读性。这就是为什么这将是我的最终解决方案:
^[0-9]+$
^\d+$
评论
这段代码中很少有SHOUTY_SNAKE_CASE变量和文本吗?!我来到这里的期望是PCG,而不是CR。很失望。
@fluffy现在很简单。您在PCG上看到的徽标表示“未完全毕业”:p
@holroy是Java,不是LOLCODE。
ArnoldC绝对是专为吵闹的东西而制作的