如何使用(正则表达式)删除java中重复的字母并且不区分大小写

时间:2013-07-28 04:08:54

标签: java regex case-insensitive

我一直试图用他们的小写字母(在java中)替换任何重复的字母。例如:

我想要一个映射的函数:

bob -> bob
bOb -> bob
bOOb -> bob
bOob -> bob
boOb -> bob
bob -> bob
Bob -> Bob
bOb -> bob

但是,我使用正则表达式(在Java中)没有成功。

我尝试了以下内容:

    String regex = "([A-za-z])\\1+";
    String str ="bOob";
    Pattern pattern = Pattern.compile(regex , Pattern.CASE_INSENSITIVE);
    Matcher matcher = pattern.matcher(str);
    System.out.println(matcher.replaceAll("$1"));

然而,这会返回bOb而不是bob。 (它适用于boOb)。

我也尝试过:

        Pattern pattern = Pattern.compile("(?i)([A-Za-z0-9])(?=\\1)", Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(str);
        return matcher.replaceAll("");

这解决了一个问题,现在bOob - > bob但是带来了另一个问题,因为现在它将boOb映射到bob。

注意:它还应该映射BOobOoboObOoObooOoOoOoOoOOb - > Bobobobobob。

我觉得在这一点上循环字符串并根据每个字符做一些逻辑可能更容易但我只是不想放弃使用正则表达式...如果存在使用正则表达式的解决方案,它是否比围绕每个角色的循环更有效?

提前致谢!

PS:我知道在传递字符串之前可以简单地减少所有内容,但这不是我想要的,因为它映射:

鲍勃 - >鲍勃

2 个答案:

答案 0 :(得分:3)

使用Matcher#group()代替$1

if (matcher.find()) {
    System.out.println(matcher.replaceAll(matcher.group(1)
                                          .toLowerCase()));
}

让您可以使用toLowerCase()

编辑 :(回应OP的评论)

Matcher#group(n)$n相同 - 它指的是 n'th 捕获组。因此,group(1)$1都会捕获O,但您可以切换捕获toLowerCase()

循环由replaceAll()而不是find()运行。初始化组需要Matcher#find(),以便group(1)在调用replaceAll()之前返回捕获。

但是,这也意味着捕获保持不变,满足您的要求,但需要重置匹配器,如 BOobbOobboObbOoObbooOoOoOoOoOOb (注意双b)。该循环现在必须由Mathcer#find()驱动,这意味着replaceAll()replaceFirst()进行交易。

String regex = "([A-Za-z])\\1+";
String str = "BOobbOobboObbOoObbooOoOoOoOoOObb";

Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(str);

while (matcher.find()) {
    str = matcher.replaceFirst(matcher.start() > 0 ? matcher.group(1)
                                    .toLowerCase() : matcher.group(1));
    matcher.reset(str);
}

System.out.println(str); // Bobobobobob
此处使用

Matcher#start()来确定匹配是否在输入的开头,而不管是否保持不变。

答案 1 :(得分:2)

我认为这是我正在寻找的代码(根据接受的答案):

public String removeRepeatedLetters(String str, boolean caseSensitive){
    if(caseSensitive){
        return this.removeRepeatedLetters(str); //uses case sensitive version
    }else{
        Pattern patternRep = Pattern.compile("([A-Za-z])(\\1+)", Pattern.CASE_INSENSITIVE);
        Matcher matcher = patternRep.matcher(str);
        String output = str;
        while(matcher.find()){
            String matchStr = matcher.group(1);
            output = matcher.replaceFirst(matchStr.toLowerCase());
            matcher = patternRep.matcher(output);
            matcher.reset();
        }
        return output;
    }   
}

它的作用是替换任何重复的字母(无论是大写字母还是大写字母),并用一个非大写字母替换它们。

我认为非常接近我想要的工作,尽管它映射了Bbob - >鲍勃。我怀疑这是因为它没有映射到Bob,这会影响我使用它的原因。

不过,如果有人能看到如何优化这一点,请随时发表评论!它确实让我烦恼了.reset(),虽然我不确定它是否是必要的。