Удаление символов через определенное количество раз

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

Например: DeleteChars("abaabbb",2); должен вывести: «abab»

У меня проблемы с тем, чтобы заставить его работать, и я действительно не знаю, где я ошибаюсь. Я чувствую, что то, что у меня есть, должно работать. Но я не очень хорошо разбираюсь в регулярных выражениях, поэтому я уверен, что именно здесь возникает проблема, но я действительно не знаю, как ее исправить.

public static String DeleteChars(String data, int deleteValue)
{
    String regex = "(.)\\1{" + deleteValue + ",}";

    StringBuffer sbuffer = new StringBuffer();
    Pattern p = Pattern.compile(regex);
    Matcher m = p.matcher(data);
    while(m.find())
    {
        m.appendReplacement(sbuffer, "");
    }
    m.appendTail(sbuffer);
    return sbuffer.toString();
}

Обновлено: добавление дополнительных случаев для ввода-вывода, чтобы получить желаемый результат.

DeleteChars("ababababababa", 2);
Expected: abab

DeleteChars("abcabcaabbcceess", 1)
Expected: abces

DeleteChars("Hey there are spaces", 2)
Expected: Hey ther arspacs

DeleteChars("absdfsdfgldfj", 0)
Expected:

В чем проблема? Это ошибка программы или результат, которого вы не ожидали?

Ishaan Javali 18.11.2018 03:32
«Но я не очень хорошо разбираюсь в регулярных выражениях, поэтому я уверен, что именно здесь возникает проблема, но я действительно не знаю, как ее исправить». - Вы пробовали отладить код? Это намного лучше, чем угадывать, в чем проблема.
Stephen C 18.11.2018 03:35

Возвращает пустую строку.

Dtb49 18.11.2018 04:18

Отладчик расскажет вам больше. Установите точки останова, посмотрите на переменные, посмотрите, что произойдет.

Stephen C 18.11.2018 05:51

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

Stephen C 18.11.2018 05:57

@StephenC прав. Регулярное выражение - плохой (возможно, неправильный) подход. Моя ставка - воспользоваться HashMap

Rcordoval 20.11.2018 04:36
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
6
66
2

Ответы 2

В этом случае нет необходимости использовать регулярное выражение. Вы можете карта для каждого символа и целого числа, которое представляет количество вхождений в строке, а затем проверить, следует ли добавлять или игнорировать (см. Комментарии к коду для получения дополнительной информации).

Фрагмент:

import java.util.HashMap;

public class Snippet {
    
    public static void main(String[] args) {
        System.out.println("output = " + DeleteChars("abaabbb", 2 ));
        System.out.println("output = " + DeleteChars("abcabcaabbcceess", 1));
        System.out.println("output = " + DeleteChars("Hey there are spaces", 2));
        System.out.println("output = " + DeleteChars("absdf\nsdf\ngld\nfj", 2));

    }
    
    public static String DeleteChars(String data, int deleteValue)
    {
        //map characters with Integers example {a=3, b=4}
        HashMap<Character, Integer> charCountMap = new HashMap<Character, Integer>(); 
        //array of string data
        char[] strArray = data.toCharArray(); 
        //output (empty at first)
        String output = "";
        for (char c : strArray) { 
            if (charCountMap.containsKey(c)) { 
                // If char is present in charCountMap, 
                // incrementing it's count by 1 
                charCountMap.put(c, charCountMap.get(c) + 1); 
            } 
            else { 
                // If char is not present in charCountMap, 
                // putting this char to charCountMap with 1 as it's value 
                charCountMap.put(c, 1); 
            }
            //if not reached max ocurrences just add the char to output string
            if (charCountMap.get(c) <= deleteValue) output = output + c;
        } 
        //print map (just informative)
        System.out.println("Map = " + charCountMap.toString().replaceAll("\n","linebreak").replaceAll("  = ", "space  = "));
        return output;
    }
    
}

Вывод:

Map = {a=3, b=4}
output = abab
Map = {a=4, b=4, c=4, s=2, e=2}
output = abces
Map = {space =3, p=1, a=2, r=2, s=2, c=1, t=1, e=5, H=1, h=1, y=1}
output = Hey ther arspacs
Map = {a=1, b=1, s=2, d=3, f=3, g=1, linebreak=3, j=1, l=1}
output = absdf
sdf
glj

Он будет соответствовать вашим тестовым примерам, а также обрабатывать разрывы строк и пробелы.

Я только что проверил это, вроде работает. Однако мне это нужно для работы с любым символом, включая пробелы и разрывы строк. Есть ли какие-то проверки, которые необходимо сделать для этого?

Dtb49 18.11.2018 04:17

Это работает, только если буквы находятся рядом друг с другом, как указано в выходных данных вашего второго примера. Результатом, которого я хочу ожидать, будет: abaabbcceedqwefff Я хочу разрешить только это количество символов в строке в целом, если это имеет смысл. Мне все равно, рядом они друг с другом или нет. Могу ли я использовать для этого регулярное выражение или мне стоит поискать другой подход?

Dtb49 19.11.2018 00:53

Можете ли вы отредактировать свой вопрос и добавить примеры ввода-вывода, чтобы мы могли его протестировать?

Rcordoval 19.11.2018 21:26

@ Dtb49 чек отредактирован. Я рассмотрел ваши тестовые примеры другим подходом

Rcordoval 20.11.2018 04:35

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

    public static String deleteChars(String data, int deleteValue) {
    HashMap<Character, Integer> compareMap = new HashMap<>();
    String returnString = "";

    // Iterate through the string. Use a hashmap to store the number of characters in the string as you iterate
    // through. Add chars until you reach the limit.
    for (int i = 0; i < data.length(); i++) {
        char charToAdd = data.charAt(i);
        Integer numberOfChars = compareMap.get(charToAdd);
        Integer valueToAdd = (numberOfChars == null) ? 1 : numberOfChars+1;
        compareMap.put(charToAdd, valueToAdd);

        //After incrementing the hashmap value, we check to see if we can add this to the return string
        if (compareMap.get(charToAdd) <= deleteValue) {
            returnString = returnString.concat(String.valueOf(charToAdd));
        }
    }
    return returnString;
}

Это работает со всеми персонажами? Как бы он справился с разрывом строки?

Dtb49 18.11.2018 04:21

@ Dtb49 Сохраняет первое deleteValue количество разрывов строки (\ n)

Josh 18.11.2018 05:00

Другие вопросы по теме