2013-04-17 67 views
2

我想創建一個方法,它將從字符串中刪除所有重複項,或者只保留基於參數的同一行中的2個字符。在一行中刪除重複的相同字符

例如:

helllllllo -> helo 

helllllllo -> hello - 這樣可以使雙字母

目前我做刪除重複:

private String removeDuplicates(String word) { 
    StringBuffer buffer = new StringBuffer(); 
    for (int i = 0; i < word.length(); i++) { 
     char letter = word.charAt(i); 
     if (buffer.length() == 0 && letter != buffer.charAt(buffer.length() - 1)) { 
      buffer.append(letter); 
     } 
    } 
    return buffer.toString(); 
} 

如果我想保持雙字母我正在考慮像私人字符串一樣的方法

doubleLetter是真的,那將返回hello沒有helo

我不知道最有效的方式做到這一點,而無需複製大量的代碼。

+0

的StringBuilder可能會更好一點 – BlackJoker

+0

你也可以simly遞增的,如果循環計數器,並添加另一個如果循環,只有追加字母,當計數器低於一個閾值---這將是一個通用版本,可以處理任意數量的重複數據(但是您應該確保在掃描最後一個字母后重新設置計數器)。 –

回答

5

爲什麼不只是使用正則表達式?

public class RemoveDuplicates { 
     public static void main(String[] args) { 
      System.out.println(new RemoveDuplicates().result("hellllo", false)); //helo 
      System.out.println(new RemoveDuplicates().result("hellllo", true)); //hello 
     } 

     public String result(String input, boolean doubleLetter){ 
      String pattern = null; 
      if(doubleLetter) pattern = "(.)(?=\\1{2})"; 
      else pattern = "(.)(?=\\1)"; 
     return input.replaceAll(pattern, ""); 
     } 
} 

(.) --> matches any character and puts in group 1. 
?=  --> this is called a positive lookahead. 
?=\\1 --> positive lookahead for the first group 

因此,總的來說,這個正則表達式本身尋找任何跟隨(積極向前)的字符。例如aa或bb等。重要的是要注意,只有第一個字符實際上是匹配的一部分,所以在單詞'hello'中,只有第一個字符匹配(部分(?= \ 1)爲不是比賽的一部分)。所以第一個l被替換爲一個空字符串,我們留下helo,它與正則表達式不匹配。

第二種模式是一樣的,但是這次我們展望第一組的兩次出現,例如helllo。另一方面,'你好'不會匹配。

看看這裏多了很多:Regex

附:如果有幫助,請自由填寫以接受答案。

+0

感謝您的回答尤金。你能簡單地爲我解釋一下正則表達式嗎? – Decrypter

+0

@Decrypter請參閱我的編輯 – Eugene

3

嘗試

String s = "helllllllo"; 
    System.out.println(s.replaceAll("(\\w)\\1+", "$1")); 

輸出

helo 
1

試試這個,這將是[評論後編輯]最有效的方法:

public static String removeDuplicates(String str) { 
    int checker = 0; 
    StringBuffer buffer = new StringBuffer(); 
    for (int i = 0; i < str.length(); ++i) { 
     int val = str.charAt(i) - 'a'; 
     if ((checker & (1 << val)) == 0) 
      buffer.append(str.charAt(i)); 
     checker |= (1 << val); 
    } 
    return buffer.toString(); 
} 

我使用的比特來標識的唯一性。

編輯:

整個邏輯是,如果一個角色已經被解析那麼它corrresponding位被下一次設置,當該字符出現,那麼它不會在字符串緩衝中添加相應的位已經設置。

+0

'buffer.append(val)'行必須用行'buffer.append(str.charAt(i))'替代(請參閱演示:https://ideone.com/AtYH8a)和'a'周圍的單引號是錯誤的,將它們替換爲標準的;) –

+0

謝謝Andrea編輯我的帖子。 – Lokesh

+0

不客氣。請注意,它有更復雜的輸入字符串的錯誤:https://ideone.com/FmiXEe應改爲https://ideone.com/HvogfI:/一些修復是需要的 –

1

this以前SO例子作爲一個起點,我想出了這個:

String str1= "Heelllllllllllooooooooooo"; 

    String removedRepeated = str1.replaceAll("(\\w)\\1+", "$1"); 
    System.out.println(removedRepeated); 

    String keepDouble = str1.replaceAll("(\\w)\\1{2,}", "$1"); 
    System.out.println(keepDouble); 

它產生:

直升機

Heelo

它所確實:

(\\w)\\1+將匹配任何字母並將其放入正則表達式捕獲組中。此組後來通過\\1+訪問。意思是它將匹配前一個字母的一個或多個重複。

(\\w)\\1{2,}與上面相同,唯一的區別是它只照顧重複超過2次的字符。這使得雙字符不變。

編輯: 重新閱讀這個問題,它似乎是你想用雙打替換多個字符。要做到這一點,只需使用這條線:

String keepDouble = str1.replaceAll("(\\w)\\1+", "$1$1");

相關問題