java - 反转单词而不改变大写或标点符号
问题描述
创建一个字符最少的程序,以反转字符串中的每个单词,同时保持单词的顺序,以及标点符号和大写字母,在它们的初始位置。
通过“单词的顺序”,我的意思是每个单词都被一个空格(“”)分隔,因此缩写等将被视为一个单词。宫缩中的撇号应该留在同一个地方。(“不要”=>“不”)。
(标点符号表示任何不是 az、AZ 或空格的字符*)。
Numbers were removed from this list due to the fact that you cannot have capital numbers. Numbers are now treated as punctuation.
例如,对于输入:
你好,我是一条鱼。
它应该输出:
Olleh,我是一个 hsif。
请注意,O 是第一个单词中的第一个字母,现在是大写字母,因为 H 之前在同一位置是大写字母。
逗号和句号也在同一个地方。
更多示例:
这个; 是一些文字!
会输出
希特; Si Emos Txet!
我试过这个:
public static String reverseWord(String input)
{
String words[]=input.split(" ");
StringBuilder result=new StringBuilder();
for (String string : words) {
String revStr = new StringBuilder(string).reverse().toString();
result.append(revStr).append(" ");
}
return result.toString().trim();
}
解决方案
这是一个符合您要求的建议。它可能看起来很长,但它只是注释和充气代码;每个人都喜欢评论。
public static String smartReverseWords(String input) {
StringBuilder finalString = new StringBuilder();
// Word accumulator, resetted after each "punctuation" (or anything different than a letter)
StringBuilder wordAcc = new StringBuilder();
int processedChars = 0;
for(char c : input.toCharArray()) {
// If not a whitespace nor the last character
if(!Character.isWhitespace(c)) {
// Accumulate letters
wordAcc.append(c);
// Have I reached the last character? Then finalize now:
if(processedChars == input.length()-1) {
reverseWordAndAppend(wordAcc, finalString);
}
}
else {
// Was a word accumulated?
if(wordAcc.length() > 0) {
reverseWordAndAppend(wordAcc, finalString);
}
// Append non-letter char to final string:
finalString.append(c);
}
processedChars++;
}
return finalString.toString();
}
private static void reverseWordAndAppend(StringBuilder wordAcc, StringBuilder finalString) {
// Then reverse it:
smartReverse(wordAcc); // a simple wordAcc.reverse() is not possible
// Append word to final string:
finalString.append(wordAcc.toString());
// Reset accumulator
wordAcc.setLength(0);
}
private static class Marker {
Integer position;
String character;
}
private static void smartReverse(StringBuilder wordAcc) {
char[] arr = wordAcc.toString().toCharArray();
wordAcc.setLength(0); // clean it for now
// Memorize positions of 'punctuation' + build array free of 'punctuation' in the same time:
List<Marker> mappedPosOfNonLetters = new ArrayList<>(); // order matters
List<Integer> mappedPosOfCapitals = new ArrayList<>(); // order matters
for (int i = 0; i < arr.length; i++) {
char c = arr[i];
if(!Character.isLetter(c)) {
Marker mark = new Marker();
mark.position = i;
mark.character = c+"";
mappedPosOfNonLetters.add(mark);
}
else {
if(Character.isUpperCase(c)) {
mappedPosOfCapitals.add(i);
}
wordAcc.append(Character.toLowerCase(c));
}
}
// Reverse cleansed word:
wordAcc.reverse();
// Reintroduce 'punctuation' at right place(s)
for (Marker mark : mappedPosOfNonLetters) {
wordAcc.insert(mark.position, mark.character);
}
// Restore capitals at right place(s)
for (Integer idx : mappedPosOfCapitals) {
wordAcc.setCharAt(idx,Character.toUpperCase(wordAcc.charAt(idx)));
}
}
编辑
我已经更新了代码以考虑您的所有要求。事实上,我们必须确保“标点符号”保持在原位(以及大写字母),但也要保持在一个单词之内,例如缩略语。
因此给定以下输入字符串:
"Hello, I am on StackOverflow. Don't tell anyone."
该代码产生以下输出:
"Olleh, I ma no WolfrEvokcats. Tno'd llet enoyna."
推荐阅读
- bash - 如何将一对线移动到前一对线的末尾
- vba - 分离数据和清理Access Table
- spring - 骆驼 3 openjdk 11 休眠/jpa java.lang.NoSuchMethodError
- r - 在组内重新排序不适用于 ggplot 条形图
- javascript - 节点 puppeteer Promise.all 一次查看不同页面时的所有问题
- python-3.x - 可以将 miniconda(或 conda)安装到现有的 python3 虚拟环境中吗?
- django - 如何从其他用户类型创建客户帐户 ID
- asp.net-mvc - Razor View Row ID 始终只为第一行传递 ID
- python - Aws lambda 函数连接到 mongodb
- visualization - 我可以为 Alloy Analyzer 指定自定义颜色(例如 RGB)以在可视化中使用吗?