множественные замены в Java - PullRequest
0 голосов
/ 05 ноября 2019

Я использую Java 1.8. У меня есть большое количество текста в буфере. В тексте есть несколько вхождений, например:

"... {NAME} собирается {PLACE} ...", бла-бла-бла.

Тогда у меня есть два массива: "{ИМЯ}; {МЕСТО} "и" Мик Джаггер; Гого "и т. Д. (Это только примеры). Я делаю на карту такие замены, как

 {NAME};Mick Jagger
 {PLACE};A Gogo

Так что я хочу сделать все замены. В этом случае есть только 2, так что это не так громоздко. Скажем, мой исходный текст находится в txt:

 for (EntrySet<String, String> entry : replacements.entrySet()) {
   txt = txt.replace(entry.getKey(), entry.getValue());
 }

Вы можете создавать изображения, если есть много замен, это может занять много времени.

Есть ли какой-нибудь лучший способ сделать всезамены, или это в основном то, что вы будете делать?

Ответы [ 2 ]

0 голосов
/ 05 ноября 2019

Чтобы не вызывать String.replace много раз, вы можете использовать регулярное выражение, которое соответствует каждому ключу замены. Затем вы можете итеративно сканировать следующий ключ замены во входной строке, используя цикл, и найти его замену, используя Map.get:

import java.util.Collection;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class ReplaceMap {
    private final Pattern p;

    public ReplaceMap(Collection<String> keys) {
        this.p = Pattern.compile(keys.stream()
            .map(ReplaceMap::escapeRegex)
            .collect(Collectors.joining("|")));
    }

    public String replace(String input, Map<String,String> subs) {
        Matcher m = p.matcher(input);
        StringBuilder out = new StringBuilder();
        int i = 0;
        while(m.find()) {
            out.append(input.substring(i, m.start()));
            String key = m.group(0);
            out.append(subs.get(key));
            i = m.end();
        }
        out.append(input.substring(i));
        return out.toString();
    }

    // from https://stackoverflow.com/a/25853507/12299000
    private static Pattern SPECIAL_REGEX_CHARS = Pattern.compile("[{}()\\[\\].+*?^$\\\\|]");
    private static String escapeRegex(String s) {
        return SPECIAL_REGEX_CHARS.matcher(s).replaceAll("\\\\$0");
    }
}

Использование:

> Map<String,String> subs = new HashMap<>();
> subs.put("{NAME}", "Alice");
> subs.put("{PLACE}", "Wonderland");
> ReplaceMap r = new ReplaceMap(subs.keySet());
> r.replace("Hello, {NAME} in {PLACE}.", subs)
"Hello, Alice in Wonderland." (String)

Это решениедолжно быть примерно таким же эффективным независимо от того, сколько пар ключ / значение замены содержится в карте subs.

0 голосов
/ 05 ноября 2019

Я бы посоветовал читать файл построчно (используя NIO), и для каждой строки вы можете повторить свою карту и заменить ее, если у вас есть что-то. Так что в этом случае вам нужно просматривать большие данные только один раз

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...