2013-04-17 41 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");

相关问题