3 回答
TA贡献1811条经验 获得超5个赞
看起来这是plusOutCodingBat 上的问题。
我对这个问题有 3 个解决方案,并编写了一个新的流媒体解决方案,只是为了好玩。
解决方案 1:循环并检查
从输入字符串中创建一个 StringBuilder,并检查每个位置的单词。如果不匹配则替换字符,如果找到则跳过单词的长度。
public String plusOut(String str, String word) {
StringBuilder out = new StringBuilder(str);
for (int i = 0; i < out.length(); ) {
if (!str.startsWith(word, i))
out.setCharAt(i++, '+');
else
i += word.length();
}
return out.toString();
}
这可能是初学者程序员的预期答案,尽管假设字符串不包含任何星体平面字符,该字符将由 2 个字符而不是 1 个字符表示。
解决方案2:用记号笔替换单词,替换其余单词,然后还原单词
public String plusOut(String str, String word) {
return str.replaceAll(java.util.regex.Pattern.quote(word), "@").replaceAll("[^@]", "+").replaceAll("@", word);
}
不是一个合适的解决方案,因为它假设某个字符或字符序列没有出现在字符串中。
注意使用Pattern.quote来防止word被方法解释为正则表达式语法replaceAll。
解决方案 3:使用正则表达式 \G
public String plusOut(String str, String word) {
word = java.util.regex.Pattern.quote(word);
return str.replaceAll("\\G((?:" + word + ")*+).", "$1+");
}
构造 regex \G((?:word)*+).,它或多或少地执行解决方案 1 正在执行的操作:
\G 确保比赛从上一场比赛结束的地方开始
((?:word)*+)挑选出 0 个或多个word- 如果有的话,以便我们可以将它们保留在替换为$1. 这里的关键是所有格量词*+,它强制正则表达式保留word它找到的任何实例。否则,当word出现在字符串末尾时,正则表达式将无法正常工作,因为正则表达式会回溯以匹配.
.不会是 any 的一部分word,因为前一部分已经挑选出所有连续出现的word并且不允许回溯。我们将把它替换为+
解决方案 4:流媒体
public String plusOut(String str, String word) {
return String.join(word,
Arrays.stream(str.split(java.util.regex.Pattern.quote(word), -1))
.map((String s) -> s.replaceAll("(?s:.)", "+"))
.collect(Collectors.toList()));
}
这个想法是将字符串拆分为word,对其余部分进行替换,然后word使用 usingString.join方法将它们连接回来。
同上,我们需要Pattern.quote避免split将 解释word为正则表达式。由于split默认情况下会删除数组末尾的空字符串,因此我们需要-1在第二个参数中使用以split单独保留这些空字符串。
然后我们从数组中创建一个流并将其余的替换为 的字符串+。在 Java 11 中,我们可以使用s -> String.repeat(s.length())。
其余的只是将 Stream 转换为 Iterable(在本例中为 List)并加入它们以获得结果
TA贡献1810条经验 获得超4个赞
您可以在一行中完成:
input = input.replaceAll("((?:" + str + ")+)?(?!" + str + ").((?:" + str + ")+)?", "$1+$2");
这可以选择捕获每个字符的任一侧的“123”并将它们放回原处(如果没有“123”则为空白):
添加回答
举报