我有以下问题说明
使用
+
符号替换字符串中的所有字符,但方法中给定字符串的实例除外
所以例如,如果给出的字符串是,abc123efg
并且他们希望我替换除了每个实例之外的每个字符,123
那么它将成为+++123+++
.
我认为正则表达式可能是最好的,我想出了这个.
str.replaceAll("[^str]","+")
Run Code Online (Sandbox Code Playgroud)
其中str是一个变量,但它不允许我使用该方法而不将其放在引号中.如果我只想替换变量字符串str我该怎么做?我用字符串手动输入它运行它,它在方法上工作,但我可以输入一个变量吗?
截至目前我相信它正在寻找字符串"str"而不是变量字符串.
这是除了两个以外的很多情况的输出权:(
开放测试用例列表:
plusOut("12xy34", "xy") ? "++xy++"
plusOut("12xy34", "1") ? "1+++++"
plusOut("12xy34xyabcxy", "xy") ? "++xy++xy+++xy"
plusOut("abXYabcXYZ", "ab") ? "ab++ab++++"
plusOut("abXYabcXYZ", "abc") ? "++++abc+++"
plusOut("abXYabcXYZ", "XY") ? "++XY+++XY+"
plusOut("abXYxyzXYZ", "XYZ") ? "+++++++XYZ"
plusOut("--++ab", "++") ? "++++++"
plusOut("aaxxxxbb", "xx") ? "++xxxx++"
plusOut("123123", "3") ? "++3++3"
Run Code Online (Sandbox Code Playgroud)
nha*_*tdh 15
看起来这是plusOut
CodingBat上的问题.
我有3个解决这个问题的方法,并为了好玩而写了一个新的流媒体解决方案.
从输入字符串中创建一个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();
}
Run Code Online (Sandbox Code Playgroud)
这可能是初学者程序员的预期答案,尽管假设字符串不包含任何星体平面字符,它将由2个字符而不是1表示.
public String plusOut(String str, String word) {
return str.replaceAll(java.util.regex.Pattern.quote(word), "@").replaceAll("[^@]", "+").replaceAll("@", word);
}
Run Code Online (Sandbox Code Playgroud)
不是一个合适的解决方案,因为它假定字符串中没有出现某个字符或字符序列.
注意使用它Pattern.quote
来防止word
被方法解释为正则表达式语法replaceAll
.
\G
public String plusOut(String str, String word) {
word = java.util.regex.Pattern.quote(word);
return str.replaceAll("\\G((?:" + word + ")*+).", "$1+");
}
Run Code Online (Sandbox Code Playgroud)
构建正则表达式\G((?:word)*+).
,它或多或少地做了解决方案1正在做的事情:
\G
确保匹配从上一场比赛的开始处开始((?:word)*+)
选出0或更多的实例word
- 如果有的话,这样我们就可以将它们保留在替换中$1
.这里的关键是占有量词*+
,它强制正则表达式保留word
它找到的任何实例.否则,当word
出现在字符串末尾时,正则表达式将无法正常工作,因为正则表达式回溯匹配.
.
将不会成为任何一部分word
,因为前一部分已经连续出现word
并且不允许回溯.我们将替换它+
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()));
}
Run Code Online (Sandbox Code Playgroud)
我们的想法是拆分字符串word
,对其余部分进行替换,然后word
使用using String.join
方法将它们连接起来.
Pattern.quote
避免split
将word
正则表达式解释为正则表达式.由于split
默认情况下会删除数组末尾的空字符串,因此我们需要-1
在第二个参数中使用split
这些空字符串.+
.在Java 11中,我们可以使用s -> String.repeat(s.length())
.这比你最初想象的要复杂一点,因为你不仅需要匹配字符,而且缺少特定的短语 - 否定的字符集是不够的.如果字符串是123,您将需要:
(?<=^|123)(?!123).*?(?=123|$)
Run Code Online (Sandbox Code Playgroud)
https://regex101.com/r/EZWMqM/1/
即 - 查看字符串开头或"123",确保当前位置后面没有123,然后懒惰重复任何字符,直到前瞻符合"123"或字符串结尾.这将匹配不在"123"子字符串中的所有字符.然后,您需要用a替换每个字符+
,之后您可以使用appendReplacement
a和a StringBuffer
来创建结果字符串:
String inputPhrase = "123";
String inputStr = "abc123efg123123hij";
StringBuffer resultString = new StringBuffer();
Pattern regex = Pattern.compile("(?<=^|" + inputPhrase + ")(?!" + inputPhrase + ").*?(?=" + inputPhrase + "|$)");
Matcher m = regex.matcher(inputStr);
while (m.find()) {
String replacement = m.group(0).replaceAll(".", "+");
m.appendReplacement(resultString, replacement);
}
m.appendTail(resultString);
System.out.println(resultString.toString());
Run Code Online (Sandbox Code Playgroud)
输出:
+++123+++123123+++
Run Code Online (Sandbox Code Playgroud)
请注意,如果inputPhrase
可以包含正则表达式中具有特殊含义的字符,则必须在连接到模式之前先将它们转义.