Вот способ сделать это без регулярных выражений.
Я заметил, что каждый раз, когда часть строки a
заменяется на b
, b
всегда будет частью конечной строки.Таким образом, вы можете игнорировать b
из строки с этого момента.
Мало того, что после замены a
на b
там останется «пробел».Замена в том месте, где должно быть b
, не может быть произведена.
Эти действия выглядят очень похоже на split
.split
увеличьте значения (сделав "пробел" между строками), выполните дальнейшие замены для каждой строки в массиве, затем соедините их обратно.
Например:
// Original
"cat dog fish dog fish cat"
// Replace cat with dog
{"", "dog fish dog fish", ""}.join("dog")
// Replace dog with fish
{
"",
{"", " fish ", " fish"}.join("fish")
""
}.join("dog")
// Replace fish with cat
{
"",
{
"",
{" ", " "}.join("cat"),
{" ", ""}.join("cat")
}.join("fish")
""
}.join("dog")
Пока что самый интуитивный способ (для меня) - сделать это рекурсивно:
public static String replaceWithJointMap(String s, Map<String, String> map) {
// Base case
if (map.size() == 0) {
return s;
}
// Get some value in the map to replace
Map.Entry pair = map.entrySet().iterator().next();
String replaceFrom = (String) pair.getKey();
String replaceTo = (String) pair.getValue();
// Split the current string with the replaceFrom string
// Use split with -1 so that trailing empty strings are included
String[] splitString = s.split(Pattern.quote(replaceFrom), -1);
// Apply replacements for each of the strings in the splitString
HashMap<String, String> replacementsLeft = new HashMap<>(map);
replacementsLeft.remove(replaceFrom);
for (int i=0; i<splitString.length; i++) {
splitString[i] = replaceWithJointMap(splitString[i], replacementsLeft);
}
// Join back with the current replacements
return String.join(replaceTo, splitString);
}
Я не думаю, что это очень эффективно.