Как найти и заменить 3 или более символов на 3 или более символов в String Java?

Мне нужно проверить, содержит ли строка строки, которые необходимо удалить, и указать, какие символы будут удалены.
Последовательность символов заменяется символами подчеркивания ("") соответственно длине последовательности, если их три или несколько смежных символов с одним и тем же символом. например, строка ", _, @, @, @, @, $, $, , #, #,!" будет преобразовано в ", _, _, _, _, _, _, $, $, _, #, #,!" После процесса исключения.
Мне нужно сделать это только с помощью String или StringBuilder, Regex и т. Д. (Только базовое кодирование Java).
Также нельзя использовать массивы. Заранее спасибо.
Вот что я пробовал:

public static void main(String[] args) {    
    String linha = "##,$$$$,%%%%,@%@@@,!!!!", validos = "$#%!@";        
        for (int i = 0; i < validos.length(); i++) {
            linha = linha.replaceAll("\\" + validos.charAt(i) + "{3,}", "_");
        }
        System.out.println (linha);
    }
}

Проблема здесь в том, что последовательность заменяется только одним «_», и я не знаю, какие символы заменяются.


person Francisco Costa    schedule 06.11.2012    source источник
comment
что ты уже испробовал? Мы не собираемся писать весь ваш код за вас.   -  person tckmn    schedule 06.11.2012
comment
Отредактируйте это в своем вопросе и отформатируйте как код.   -  person tckmn    schedule 06.11.2012
comment
отредактируйте исходный пост, а не комментируйте   -  person Adrian Shum    schedule 06.11.2012
comment
Я уже видел это, мне не очень помогло.   -  person Francisco Costa    schedule 06.11.2012
comment
_, _, @, @, @, @, $, $, , #, #,! этот пример выглядит неверным в соответствии с вашим описанием.   -  person Bhesh Gurung    schedule 06.11.2012


Ответы (4)


Конечно, вы можете делать это разными способами, и, вероятно, это хорошее упражнение для самостоятельного выполнения. Здесь у вас есть базовая реализация, использующая только базовые структуры цикла и ничего особенного, как библиотеки StringUtils... Обратите внимание, что ваша предыдущая реализация цикла пропустила бы несколько вхождений одного и того же символа, повторяющихся в разных местах linha.

static int index(String lookInStr, char lookUpChr) {
    return lookInStr.indexOf(new String(new char[] { lookUpChr, lookUpChr, lookUpChr }));
}

public static void main(String[] args) {
    String linha = "####,@@@@@@@@,$$$$,%%%%,@%@@@,!!!!", validos = "$#%!@";
    for (int i = 0; i < validos.length(); i++) {
        char currentSearchChar = validos.charAt(i);
        do {
            int index = index(linha, currentSearchChar);
            if (index >= 0) {
                int count = -1;
                do {
                    count++;
                } while (linha.charAt(count + index) == currentSearchChar && count + index < linha.length() - 1);
                String replacementSeq = "";
                for (int j = 0; j < count; j++) {
                    replacementSeq += "-";
                }
                linha = linha.replaceAll("\\" + validos.charAt(i) + "{" + count + ",}", replacementSeq);
            }
        } while (index(linha, currentSearchChar) >= 0);
    }
    System.out.println(linha);
}
person David Bejar    schedule 06.11.2012
comment
Большое спасибо! Но все еще не служит моим целям, я не могу использовать char[], но я могу работать с этим, это здорово. - person Francisco Costa; 06.11.2012
comment
Извините, это не лучший ответ, Final Zero пока лучший ответ, но все еще жду... - person Francisco Costa; 06.11.2012

Если вы пытаетесь заменить сразу три символа и вместо этого хотите три символа подчеркивания, вам просто не хватает этого:

linha = linha.replaceAll("\\" + validos.charAt(i) + "{3,}", "___");

Если вы хотите, чтобы они были разделены запятыми:

linha = linha.replaceAll("\\" + validos.charAt(i) + "{3,}", "_,_,_");
person David Bejar    schedule 06.11.2012
comment
Проблема в том, что если в последовательности 4 символа, то должно быть 4 знака подчеркивания, если 5, то пять знаков подчеркивания и так далее... - person Francisco Costa; 06.11.2012

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

static String convert(String s) {
    StringBuilder sb = new StringBuilder();

    for(int i = 0; i < s.length(); i++) {
        char c = s.charAt(i);
        StringBuilder tempSb = new StringBuilder();

        for(; i < s.length(); i++) {
            char d = s.charAt(i);

            if(d != c) {
                i--;
                break;
            } else {
                tempSb.append(d);
            }
        }

        String t = tempSb.toString();
        if(t.length() < 3) {
            sb.append(t);
        } else {
            sb.append(repeat("_", t.length()));
        }
    }

    return sb.toString();
}

public static void main(String[] args) {
    String x = convert("##,$$$$,%%%%,@%@@@,!!!!");
    System.out.println(x); // ##,____,____,@%___,____
}

А вот простой метод повторения:

static String repeat(String s, int repeatCount) {
    StringBuilder sb = new StringBuilder();

    for(int i = 0; i < repeatCount; i++) {
        sb.append(s);
    }

    return sb.toString();
}
person Tespa42    schedule 06.11.2012
comment
Спасибо FinalZero за ваш ответ, это действительно работает, есть только одна проблема, во 2-м цикле, это работает, но это неправильно программировать, понимаете, о чем я? - person Francisco Costa; 08.11.2012
comment
Вы имеете в виду, что неправильно создавать цикл for, который пропускает инициализацию переменной? Если это делает его непригодным для вас, то я не уверен, что сказать. Все, что вы напишете для замены, будет просто более сложной имитацией или скрытием в библиотечной функции. - person Tespa42; 09.11.2012
comment
Это было объяснение, которое сказал мне один из моих учителей: Первое - 2 цикла соединились в цепочку для совместного использования счетчика. Во-вторых, они фальсифицируют обновление счетчика циклов за пределами внутреннего цикла. Цикл for - это своего рода цикл, который должен вести себя хорошо, т.е. не должен каким-либо образом изменять способ обновления счетчика, особенно внутри цикла! - person Francisco Costa; 10.11.2012
comment
Критерии учителей кажутся довольно произвольными; Мне интересно, как они хотят, чтобы это было сделано тогда. - person Tespa42; 10.11.2012

На самом деле это не реализовано, но вы можете посмотреть на это:

В Matcher есть find(int start), start() и end()

Создайте шаблон для «3 или более повторяющихся символов» (вы можете обратиться к комментарию в своем вопросе).

псевдокод примерно такой:

int lastEndingPosition = 0;
StringBuilder sb;

while (matcher can find next group) {
  // add the unmatched part
  sb.append( substring of input string from lastEndingPosition to matcher.start() ); 

  // add the matched part
  sb.append( "-" for matcher.end() - matcher.start() times);
  lastEndingPosition = matcher.end();
}
sb.append( substring of input string from lastEndingPosition to the end);

Вероятно, есть более элегантный способ сделать это. Это всего лишь одна альтернатива

person Adrian Shum    schedule 06.11.2012
comment
Спасибо, я попробую, но если есть более элегантный способ сделать это, конечно, мне было бы интересно... - person Francisco Costa; 06.11.2012