为了账号安全,请及时绑定邮箱和手机立即绑定

Java正则表达式:除给定字符串的实例外,用`+`替换所有字符

Java正则表达式:除给定字符串的实例外,用`+`替换所有字符

慕码人2483693 2021-09-15 16:57:28
我有以下问题用+符号替换字符串中的所有字符,方法中给定字符串的实例除外因此,例如,如果给定的字符串是,abc123efg并且他们希望我替换除每个实例之外的每个字符,123那么它将变为+++123+++.我认为正则表达式可能是最好的,我想出了这个。str.replaceAll("[^str]","+")其中 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"
查看完整描述

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)并加入它们以获得结果


查看完整回答
反对 回复 2021-09-15
?
慕莱坞森

TA贡献1810条经验 获得超4个赞

您可以在一行中完成:

input = input.replaceAll("((?:" + str + ")+)?(?!" + str + ").((?:" + str + ")+)?", "$1+$2");

这可以选择捕获每个字符的任一侧的“123”并将它们放回原处(如果没有“123”则为空白):


查看完整回答
反对 回复 2021-09-15
  • 3 回答
  • 0 关注
  • 230 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信