我需要将字符串中每个单词的第一个字母大写,但这并不像看上去那么容易,因为这个单词被认为是字母、数字、“\”、“-”、“`”的任意序列,而所有其他字符被认为是分隔符,即在它们之后的下一个字母必须大写。
示例程序应该做什么:
输入:“#他和我!“风险”
输出应该是:“#他和我!“风险”
这里有些问题听起来很相似,但解决方法确实没有帮助。例如:
String output = Arrays.stream(input.split("[\\s&]+"))
.map(t -> t.substring(0, 1).toUpperCase() + t.substring(1))
.collect(Collectors.joining(" "));
因为在我的任务中可能有各种分隔符,所以这个解决方案不起作用。
4条答案
按热度按时间5jvtdoz21#
我需要把每个单词的首字母大写
这里有一个方法。诚然,这可能会更长,但您需要将第一个字母更改为大写(而不是第一个数字或第一个非字母),这需要一个helper方法。否则就容易多了。其他一些人似乎忽略了这一点。
建立单词模式,测试数据。
现在只需根据已建立的正则表达式查找字符串中的每个连续单词。找到每个单词后,它会将单词中的第一个字母改为大写,然后将其放入字符串缓冲区中找到匹配项的正确位置。
印刷品
因为单词可以以数字开头,要求将第一个字母(不是字符)转换为大写。此方法查找第一个字母,将其转换为大写并返回新字符串。所以呢
01_hello
会变成01_Hello
```public static String upperFirstLetter(String word) {
char[] chs = word.toCharArray();
for (int i = 0; i < chs.length; i++) {
if (Character.isLetter(chs[i])) {
chs[i] = Character.toUpperCase(chs[i]);
break;
}
}
return String.valueOf(chs);
}
e3bfsja22#
你不能轻易地使用split,split会消除分隔符,只给你中间的东西。因为你需要分离器,没有人能做到。
一个真正肮脏的把戏是使用一种叫做“向前看”的东西。传递给split的参数是一个正则表达式。regexp中的大多数“字符”都具有使用匹配输入的属性。如果你这样做了
input.split("\\s+")
然后,这不仅仅是对空白进行分割,它还会消耗它们:空白不再是字符串数组中单个条目的一部分。但是,请考虑
^
以及$
. 或者\\b
. 这些仍然匹配的东西,但不消耗任何东西。您不使用“字符串结尾”。事实上,^^^hello$$$
匹配字符串"hello"
也一样。您可以自己使用lookahead:在存在lookahead但不使用它时进行匹配:不幸的是,这样做“有效”,因为它节省了分隔符,但并没有让您离解决方案更近:
你也可以用lookback,但它是有限的;例如,他们不做可变长度。
结论应该很快变成:实际上,用
split
是个错误。然后,一旦split离开了表,您就不应该再使用streams了,或者:一旦您需要了解流中前一个元素的信息来完成任务,streams就不能很好地工作:字符流不能工作,因为您需要知道前一个字符是否是非字母。
一般来说,“我想做x,用y”是个错误。保持开放的心态。这类似于问:“我想涂黄油,然后用锤子去做。”。哦,你也许可以这么做,但是,呃,为什么?抽屉里有黄油刀,只是。。把锤子放下,那是烤面包。不是钉子。
彼此彼此。
一个简单的循环可以解决这个问题,没有问题:
很简单。效率高。易于阅读。易于修改。例如,如果您想使用“any non-letter counts”,琐碎:
atBreak = Character.isLetter(c);
.与流解决方案相比,流解决方案脆弱、怪异、效率低得多,并且需要一个regexp,任何人都需要半页的注解才能理解它。
你能用溪流做这个吗?对。你也可以用锤子给烤面包涂黄油。但这不是个好主意。把锤子放下!
x6yk4ghg3#
在遍历字符串中的字符时,可以使用一个简单的fsm,其中有两种状态,一种是在一个单词中,另一种不是在一个单词中。如果您不在单词中,而下一个字符是字母,请将其转换为大写,否则,如果它不是字母或您已经在单词中,只需复制它而不作修改。
注意:我用过
codePoints()
,appendCodePoint(int)
,和int
以便正确处理基本多语言平面(代码点大于64k)之外的字符。az31mfrm4#
可以拆分字符串并保留分隔符,因此考虑到对分隔符的要求:
单词被认为是任何字母、数字、“\”、“-”、“
”的序列,而所有其他字符被认为是分隔符 在结果数组中保留分隔符的模式是:
"((?<=[^-\\w])|(?=[^-
\w]))":
[^-\\w]
:除-
,反勾号和单词字符\w
:[A-Za-z0-9_]
然后,“单词”大写,分隔符保持原样:测验:
输出:
更新
如果不仅需要处理ascii字符集,而且还需要应用于其他字母或字符集(例如西里尔字母、希腊语等),posix类
\\p{IsWord}
可以使用,需要使用模式标志启用unicode字符的匹配(?U)
:测试:
输出: