2013-07-28 36 views
4

我一直在試圖做的是用他們的小寫字母(在java中)替換任何重複的字母。例如:如何使用(正則表達式)刪除java中的重複字母,並區分大小寫不敏感

我想映射的功能:

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

不過,我一直沒有成功做到這一點使用regexs(在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")); 

然而,這將返回鮑勃和不鮑勃。 (它對boOb有效)。

我也試過:

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

此解決一個問題,現在布布 - >鮑勃但因爲現在它映射布布鮑勃帶來了另一個問題。

注意:它也應該映射BOobOoboObOoObooOoOoOoOoOOb - > Bobobobobob。

我覺得在這一點上它可能更容易循環字符串,並根據每個字符做一些邏輯,但我只是不想放棄使用正則表達式......如果存在使用正則表達式的解決方案,是否更有效率比循環遍歷每個角色?

在此先感謝!

PS:據我所知,人們可以只需更低的情況下,一切傳遞字符串之前,不過,那不是我想要的東西,因爲它映射:

鮑勃 - >鮑勃

+0

你想映射bOb - >鮑勃,但也鮑勃 - >鮑勃?你需要添加第一個字母不能轉換的要求 – morgano

回答

3

使用Matcher#group()代替$1這裏

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

然後讓您使用toLowerCase()

編輯:(響應OP的評論)

Matcher#group(n)是一樣的$n - 它是指第n個捕獲組。所以,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()這裏用來標識匹配是否在輸入的開始處,其中情況保持不變。

+0

我留下了深刻的印象,同時也有點困惑。我想知道你是否可以解釋一下.group(1)的功能?我不明白的部分是,爲什麼你不必通過比賽來解決問題,比如做類似這樣的事情: int i = 0; (matcher.find()){ \t \t System.out.println(matcher.replaceAll(matcher.group(i).toLowerCase())); i ++; \t \t} 與你所做的有什麼不同?另外,我的$ 1和你的組(x)函數有什麼區別?我猜你得到一個點的比賽和「強制」一個小寫。正確? –

+0

順便說一句,我留下深刻印象的原因是因爲它的工作正是我所需要的,它映射BOobOoboObOoObooOoOoOoOoOOb - > Bobobobobob。很酷。 –

+1

@CharlieParker請檢查更新。我已經添加了第一個字母大寫修正。 –

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(),儘管我不確定它是否有問題。

+1

啊,我在發佈時正在更新我的答案。請再看一下。除了你可以避免每次創建一個新的「匹配器」,它或多或少都是相同的。我已經添加了修復以保留第一個字母,因爲它也是。 –

相關問題