Есть несколько паттернов, которые я объединяю через join("|")
.
Задача, каждый паттерн может удовлетворять N-количеству совпадений
Например: (и\\s*\\.*\\s*т\\s*\\.?\\s*д\\s*\\.)
Каждое совпадение забиваем в HashMap<String, String>
, где <Хэш, Совпадение>
Каждое совпадение заменить на хэш в исходной строке.
Проблема: Почему-то Matcher.find()
делает только одну итерацию цикла и заменяет все паттерны через пайп |
на один и то же хэш.
Что делать в таком случае, кроме как составлять вручную списки слов?
UPD
Упрощенный пример для данной задачи (https://ideone.com/d1UhRh):
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.HashMap;
public class Main
{
static void processString(String line)
{
Pattern p = Pattern.compile("(1\\%?|2|3|4)"); // 5 Вариантов паттернов для теста
Matcher m = p.matcher(line); // Естественно в реальной задаче намного больше
HashMap<String, String> map = new HashMap<>();
int i = 0;
while (m.find()) {
// Здесь я ожидаю 5 итераций для каждого вхождения 1, 1%, 2, 3, 4 и замены их на ААА1, ААА1%, ААА2 и т.д.
// Эти вхождения добавить в HashMap (map) ниже
i++;
System.out.println("Нужно заменить " + m.group() + " на AAA" + i);
// Добавить $1 в хэшмап !!
// map.put(?)
// То есть если я передаю все 5 паттернов, то в map должно быть 5 записей
line = m.replaceAll("AAA$1");
}
System.out.println("\n\n" + line);
}
public static void main(String[] args)
{
processString(" 1 2 3 4 4 2 1% 1% 1 2 3 ");
}
}
Результат:
AAA1 AAA1 AAA1 AAA1 AAA1 AAA1 AAA1 AAA1 AAA1 AAA1 AAA1
Ожидаемый результат:
AAA1 AAA2 AAA3 AAA4 AAA4 AAA2 AAA1% AAA1% AAA1 AAA2 AAA3
UPD 2
Добавил уточнение по вопросу по поводу HashMap
Поиск производится только один раз потому как Matcher.replaceAll
заменяет все вхождения в исходной строке, после чего перезапускает matcher
:
This method first resets this matcher. It then scans the input sequence looking for matches of the pattern.
Если нужно заменять вхождения по очереди, то можно воспользоваться Matcher.appendReplacement
и Matcher.appendTail
:
StringBuffer sb = new StringBuffer();
while (m.find()) {
i++;
m.appendReplacement(sb, "AAA"+i);
}
m.appendTail(sb);
System.out.println("\n\n" + sb);
Если нужно сохранять вхождения в Map
, то можно обрабатывать каждое и запоминать хэши:
HashMap<String, String> map = new HashMap<String,String>();
StringBuffer sb = new StringBuffer();
while (m.find()) {
String group = m.group();
String replacement;
if(map.containsKey(group)) {
//уже есть хэш
replacement = map.get(group);
} else {
//создаем и запоминаем новый хэш
i++;
replacement = "AAA"+i;
map.put(group, replacement);
}
m.appendReplacement(sb, replacement);
}
m.appendTail(sb);
Количество итераций при этом будет равно количеству вхождений, а не количеству уникальных вхождений.
Здесь для удобства используется отображение Совпадение -> Хэш
, а не Хэш -> Совпадение
как в вопросе, но при желании можно параллельно вести и обратное отображение.
Добавьте обработку того, что 1
и 1%
сводятся к одному хэшу по вкусу. Либо используйте выражение (1|2|3|4)
, а проценты оставляйте без изменений.
Пример на Ideone.
Оборудование для ресторана: новинки профессиональной кухонной техники
Частный дом престарелых в Киеве: комфорт, забота и профессиональный уход
мне нужно придумать алгоритм, который будет формировать плейлист из треков длительностью 1 частреки находятся в 2 разных папках
Добрый день, как можно моментально отследить кнопку Power? В этом примере кода она срабатывает только после того, как пройдет некоторое время...
Есть массив слов и в каждом слове от 2 до 10 строчных латинских буквС помощью StringBuffer удалить все вхождения "th"