将所有 A 替换为 B,将所有 B 替换为 A

Replace all A with B and replace all B with A

假设我想切换某些词对。比如说,我想用 dogscatsmice老鼠,所以

This is my opinion about dogs and cats: I like dogs but I don't like cats. This is my opinion about mice and rats: I'm afraid of mice but I'm not afraid of rats.

变成

This is my opinion about cats and dogs: I like cats but I don't like dogs. This is my opinion about rats and mice: I'm afraid of rats but I'm not afraid of mice.

天真的方法

text = text.replace("dogs", "cats")
           .replace("cats", "dogs")
           .replace("mice", "rats")
           .replace("rats", "mice")

是有问题的,因为它可以对同一个词进行多次替换。以上任何一个例句都会变成

This is my opinion about dogs and dogs: I like dogs but I don't like dogs. This is my opinion about mice and mice: I'm afraid of mice but I'm not afraid of mice.

替换字符串对同时防止某些内容被多次替换的最简单算法是什么?

使用您认为合适的字符串搜索算法,只要它能够搜索正则表达式即可。搜索与您要交换的所有单词匹配的正则表达式,例如dogs|cats|mice|rats。为结果维护一个单独的字符串(在许多语言中,这需要是某种 StringBuilder 以便快速重复附加),最初为空。对于每个匹配项,您都在前一个匹配项的末尾(或字符串的开头)和当前匹配项之间附加字符,然后将适当的替换项(大概是从哈希图中获得)附加到结果中。

大多数标准库应该允许您使用内置方法轻松地做到这一点。有关 Java 示例,请参阅 Matcher.appendReplacement(StringBuffer, String) 的文档。我记得在 C# 中也这样做过,使用一个功能,您可以在其中指定一个 lambda 函数,该函数决定用什么替换每个匹配项。

一种避免任何意外结果的天真的解决方案是用临时字符串替换每个字符串,然后用最终字符串替换临时字符串。但是,这假设您可以形成一个已知 而不是 的字符串,例如

text = text.replace("dogs", "{]1[}")
           .replace("cats", "{]2[}")
           .replace("mice", "{]3[}")
           .replace("rats", "{]4[}")
           .replace("{]2[}", "dogs")
           .replace("{]1[}", "cats")
           .replace("{]4[}", "mice")
           .replace("{]3[}", "rats")

我承认我对正则表达式不是很熟悉,所以我的想法是创建一个数组然后循环遍历元素以查看是否应该替换它。先split()把句子变成单词数组:

String text = "This is my opinion about dogs and cats: I like dogs but I don't like cats.";
String[] sentence = text.split("[^a-zA-Z]"); //can't avoid regex here

然后使用包含一系列if语句的for循环来替换单词:

for(int i = 0; i < sentence.length; i++) {
    if(sentence[i].equals("cats") {
        sentence[i] = "dogs";
    }
    //more similar if statements
}

现在 sentence[] 包含带单词的新句子。一些正则表达式魔法应该允许你也保留标点符号。我希望这对您有所帮助,如果有任何可以改进的地方,请告诉我。