問題は、次の置換のためにスキャンを再開し、最初に最短の入力をスキャンすることです。 abc
前a
をスキャンすることで
a
が既にabc
のためにスキャンする前に、何か他のものに置き換えられているので、あなたは、abc
に一致することはありません。最初に長さをスキャンする部分を並べ替えて、commented by rgettmanとします。
入力ごとにスキャンを再開することで、置換値の内容を置き換えることができます。例えば。あなたがa
前b
をスキャンすれば、b
はfalse
によって置き換えられますが、その後false
でa
はb
その結果、true
によって置き換えられますftruelse
に置き換え始めます。
第2の問題を解決し、パフォーマンスを向上させるには、入力を1回スキャンするだけです。
一度入力をスキャンする最も簡単な方法は、複数のテキストのいずれかの走査は、即ち、第1 |
、最長のキーによって分離されたキーをリスト、abc|a|b
ような正規表現を使用することです。
置換マッピングが何でもかまいませんと仮定すると、Map
から正規表現を動的に構築する必要があります。キーとマップの値の両方を引用することを覚えておいてください。したがって、特殊文字は正規表現の特殊文字として扱われず、例えば一致する任意の文字.
。ここ
正規表現交換ループを使用して、すべてのことを実行する(ジャワ8)方法であって
public static String replace(String input, Map<String, String> replacementValues) {
String regex = replacementValues.keySet().stream()
.sorted(Comparator.comparingInt(String::length).reversed()
.thenComparing(Function.identity()))
.map(Pattern::quote)
.collect(Collectors.joining("|"));
StringBuffer buf = new StringBuffer(input.length() + 16);
Matcher m = Pattern.compile(regex).matcher(input);
while (m.find())
m.appendReplacement(buf, Matcher.quoteReplacement(replacementValues.get(m.group())));
return m.appendTail(buf).toString();
}
テスト
Map<String, String> map = new HashMap<>();
map.put("a", "true");
map.put("b", "false");
map.put("abc", "true");
System.out.println(replace("abc|a&b", map));
出力
true|true&false
スキャンは言葉ではなく、ストリングと一致し、コンパイルする正規表現を変更する必要がある場合:
Pattern.compile("\\b(?:" + regex + ")\\b")
長さによって減少ソートあなたの鍵は、その順序でそれらを適用します。 – rgettman
あなたは3つの答えを持っていますが、すべてあなたの問題を解決しています。以前あなたが私の答えを受け入れてコメントしたので(あなたのコメントは削除していますが)、あなたはそれらを見たことが分かります。どうして?人々はあなたを助けるために真剣に取り組んでいます –