2013-04-17 4 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(); 
} 

Если я хочу сохранить двойные буквы Я думал о том, что у меня есть такой метод, как private String removeDuplicates(String word, boolean doubleLetter)

Когда 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» сопоставляется только первый l (часть (? = \ 1) равна НЕ ЧАСТЬ матча). Таким образом, первый l заменяется пустой строкой, и мы остаемся с helo, который не соответствует регулярному выражению

Второй шаблон - это то же самое, но на этот раз мы смотрим вперед для двух вхождений первой группы, для пример helllo. С другой стороны, «привет» не будет соответствовать.

Посмотрите здесь намного больше: Regex

P.S. Заполните ответ, если это поможет.

+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(); 
} 

Я использую биты, чтобы определить уникальность.

EDIT:

Вся логика в том, что если персонаж был разобран, то его corrresponding бит установлен, и в следующий раз, когда этот персонаж приходит тогда он не будет добавлен в буфер строк соответствующий бит уже установлен.

+0

строка 'buffer.append (val)' должна быть заменена линией 'buffer.append (str.charAt (i))' (см. Demo: https://ideone.com/AtYH8a) и одиночная цитата вокруг «а» ошибочна, замените их на стандартную;) –

+0

Спасибо Андреа отредактировал мое сообщение. – 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); 

Это дает:

HELO

Heelo

Что это .:

(\\w)\\1+ будет соответствовать любой букве и поместить ее в группу захвата регулярных выражений. К этой группе можно получить доступ через \\1+. Это означает, что он будет соответствовать одному или нескольким повторениям предыдущей буквы.

(\\w)\\1{2,} такой же, как и выше, с той лишь разницей, что он следит за только символами, которые повторяются более чем в 2 раза. Это оставляет двойные символы нетронутыми.

EDIT: Перечитайте вопрос, и кажется, что вы хотите заменить несколько символов на парные. Чтобы сделать это, просто использовать эту строку:

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

Смежные вопросы