По сути, я пытаюсь удалить любые повторы символа после того, как он был найден определенное количество раз. Таким образом, учитывая строку и целое число для количества вхождений, разрешено удалить его после того, как это число было достигнуто.
Например: 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:
Возвращает пустую строку.
Отладчик расскажет вам больше. Установите точки останова, посмотрите на переменные, посмотрите, что произойдет.
Также я считаю, что логика вашего кода неверна. Я вообще считаю, что эту проблему нельзя решить с помощью регулярных выражений.
@StephenC прав. Регулярное выражение - плохой (возможно, неправильный) подход. Моя ставка - воспользоваться HashMap




В этом случае нет необходимости использовать регулярное выражение. Вы можете карта для каждого символа и целого числа, которое представляет количество вхождений в строке, а затем проверить, следует ли добавлять или игнорировать (см. Комментарии к коду для получения дополнительной информации).
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
Он будет соответствовать вашим тестовым примерам, а также обрабатывать разрывы строк и пробелы.
Я только что проверил это, вроде работает. Однако мне это нужно для работы с любым символом, включая пробелы и разрывы строк. Есть ли какие-то проверки, которые необходимо сделать для этого?
Это работает, только если буквы находятся рядом друг с другом, как указано в выходных данных вашего второго примера. Результатом, которого я хочу ожидать, будет: abaabbcceedqwefff Я хочу разрешить только это количество символов в строке в целом, если это имеет смысл. Мне все равно, рядом они друг с другом или нет. Могу ли я использовать для этого регулярное выражение или мне стоит поискать другой подход?
Можете ли вы отредактировать свой вопрос и добавить примеры ввода-вывода, чтобы мы могли его протестировать?
@ Dtb49 чек отредактирован. Я рассмотрел ваши тестовые примеры другим подходом
Если вы ищете решение, в котором не используется регулярное выражение, этот параметр использует хэш-карту для хранения количества каждого символа в строке. Это будет работать с любой строкой, а не только по алфавиту.
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 Сохраняет первое deleteValue количество разрывов строки (\ n)
В чем проблема? Это ошибка программы или результат, которого вы не ожидали?