我有以下问题,它说明
将字符串中的所有字符替换为
+
符号,但方法中给定字符串的实例除外
例如,如果给定的字符串是abc123efg
,而他们希望我替换除123
实例之外的所有字符,那么它将变为+++123+++
。
我认为正则表达式可能是最好的,所以我想出了这个。
str.replaceAll("[^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"
发布于 2018-09-13 14:21:19
看起来这就是CodingBat上的plusOut
问题。
对于这个问题,我有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
来防止replaceAll
方法将word
解释为正则表达式语法。
解决方案3:使用\G
的正则表达式
public String plusOut(String str, String word) {
word = java.util.regex.Pattern.quote(word);
return str.replaceAll("\\G((?:" + word + ")*+).", "$1+");
}
构造正则表达式\G((?:word)*+).
,它或多或少地完成了solution 1正在做的事情:
\G
确保匹配从前一个匹配留下的位置开始,off((?:word)*+)
挑选出0个或更多个word
实例-如果有的话,这样我们就可以用$1
替换它们。这里的关键是所有格量词*+
,它强制正则表达式保留它找到的word
的任何实例。否则,当字符串末尾出现word
时,正则表达式将无法正常工作,因为匹配.
.
的正则表达式回溯将不会是任何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
拆分字符串,对其余部分进行替换,然后使用String.join
方法将它们与word
连接起来。
Pattern.quote
来避免split
将word
解释为正则表达式。由于split
在默认情况下会删除数组末尾的空字符串,因此我们需要在第二个参数中使用-1
来使split
保留这些空字符串。+
的字符串。在Java11中,我们可以使用s -> String.repeat(s.length())
。发布于 2018-09-13 13:26:49
这可能比您最初认为的要复杂一些,因为您不仅需要匹配字符,而且缺少特定的短语-一个被否定的字符集是不够的。如果字符串是123,则需要:
(?<=^|123)(?!123).*?(?=123|$)
https://regex101.com/r/EZWMqM/1/
也就是说,对于字符串的开头或"123",请确保当前位置后面没有123,然后延迟重复任何字符,直到lookahead匹配"123“或字符串的结尾。这将匹配不在"123“子字符串中的所有字符。然后,您需要将每个字符替换为+
,然后您可以使用appendReplacement
和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());
输出:
+++123+++123123+++
请注意,如果inputPhrase
可以在正则表达式中包含具有特殊含义的字符,则在连接到模式之前必须首先对它们进行转义。
发布于 2018-09-13 14:21:11
你可以用一行代码来完成:
input = input.replaceAll("((?:" + str + ")+)?(?!" + str + ").((?:" + str + ")+)?", "$1+$2");
这将选择性地捕获每个字符的两侧的"123“,并将它们放回原处(如果没有”123“,则为空):
https://stackoverflow.com/questions/52306904
复制相似问题