使用正则表达式将字符串中的序列替换为已修改的字符

时间:2012-12-06 00:59:43

标签: java regex string replace

我正在尝试使用正则表达式解决codingbat问题,无论它是否在网站上有效。

到目前为止,我有以下代码,它们不会在两个连续的相等字符之间添加*。相反,它只是推翻它们并用一个字符串替换它们。

public String pairStar(String str) {
    Pattern pattern = Pattern.compile("([a-z])\\1", Pattern.CASE_INSENSITIVE);
    Matcher matcher = pattern.matcher(str);
    if(matcher.find())
    matcher.replaceAll(str);//this is where I don't know what to do
    return str;
}

我想知道如何继续使用正则表达式并替换整个字符串。如果需要,我认为递归系统可以提供帮助。

4 个答案:

答案 0 :(得分:2)

这有效:

while(str.matches(".*(.)\\1.*")) {
    str = str.replaceAll("(.)\\1", "$1*$1");
}
return str;

正则表达式的解释:

搜索正则表达式(.)\\1

  • (.)表示“任意字符”(.),括号创建一个组 - 第1组(第一个左括号)
  • \\1,正则表达式为\1(java文字String必须使用另一个反斜杠转义反斜杠)表示“第一个组” - 这种术语称为“返回参考“

所以(.)\1一起意味着“任何重复的角色”


替换正则表达式$1*$1

  • $1字词表示“作为第1组捕获的内容”


递归解决方案:

从技术上讲,该网站上要求的解决方案是一个递归解决方案,所以这里是递归实现:

public String pairStar(String str) {
    if (!str.matches(".*(.)\\1.*")) return str;
    return pairStar(str.replaceAll("(.)\\1", "$1*$1"));
}

答案 1 :(得分:1)

我不懂java,但我相信在java或者正则表达式中有字符串的替换函数。你的匹配字符串是

([a-z])\\1

替换字符串将是

$1*$1

经过一番搜索,我认为你正在寻找这个,

str.replaceAll("([a-z])\\1", "$1*$1").replaceAll("([a-z])\\1", "$1*$1");

答案 2 :(得分:1)

FWIW,这是一个非递归的解决方案:

public String pairStar(String str) {
  int len = str.length();
  StringBuilder sb = new StringBuilder(len*2);
  char last = '\0';
  for (int i=0; i < len; ++i) {
    char c = str.charAt(i);
    if (c == last) sb.append('*');
    sb.append(c);
    last = c;
  }
  return sb.toString();
}

答案 3 :(得分:1)

这是我自己的解决方案。

递归解决方案(可能或多或少是问题所针对的解决方案)

public String pairStar(String str) {
    if (str.length() <= 1) return str;
    else return str.charAt(0) +
                (str.charAt(0) == str.charAt(1) ? "*" : "") +
                pairStar(str.substring(1));
}

如果你想抱怨substring,那么你可以编写一个辅助函数pairStar(String str, int index)来完成实际的递归工作。

正则表达式单线程单功能呼叫解决方案

public String pairStar(String str) {
  return str.replaceAll("(.)(?=\\1)", "$1*");
}

两种解决方案都具有相同的精神。它们都检查当前字符是否与下一个字符相同。如果它们相同,则在两个相同的字符之间插入*。然后我们继续检查下一个字符。这是为了从输入a*a*a*a生成预期输出aaaa

"(.)\\1"的正常正则表达式解决方案有一个问题:每个匹配消耗2个字符。结果,我们无法比较第二个字符后面的字符是否是相同的字符。前瞻用于解决此问题 - 它将与下一个字符进行比较而不消耗它。

这类似于递归解决方案,我们比较下一个字符str.charAt(0) == str.charAt(1),同时在子字符串上递归调用函数,只删除当前字符pairStar(str.substring(1)