Algorithm 用B替换所有A,用A替换所有B

Algorithm 用B替换所有A,用A替换所有B,algorithm,replace,language-agnostic,Algorithm,Replace,Language Agnostic,假设我想切换某些单词对。比如说,我想把狗换成猫,把老鼠换成老鼠,这样 这是我对猫和狗的看法:我喜欢狗,但我不喜欢猫。这是我对老鼠的看法:我怕老鼠,但我不怕老鼠 变成 这是我对猫和狗的看法:我喜欢猫,但我不喜欢狗。这是我对老鼠的看法:我怕老鼠,但我不怕老鼠 天真的方法 text = text.replace("dogs", "cats") .replace("cats", "dogs") .replace("mice", "rats")

假设我想切换某些单词对。比如说,我想把狗换成猫,把老鼠换成老鼠,这样

这是我对猫和狗的看法:我喜欢狗,但我不喜欢猫。这是我对老鼠的看法:我怕老鼠,但我不怕老鼠

变成

这是我对猫和狗的看法:我喜欢猫,但我不喜欢狗。这是我对老鼠的看法:我怕老鼠,但我不怕老鼠

天真的方法

text = text.replace("dogs", "cats")
           .replace("cats", "dogs")
           .replace("mice", "rats")
           .replace("rats", "mice")
是有问题的,因为它可以多次替换相同的单词。上述例句中的任何一个都会变成

这是我对狗和狗的看法:我喜欢狗,但我不喜欢狗。这是我对老鼠和老鼠的看法:我怕老鼠,但我不怕老鼠


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

使用您认为合适的字符串搜索算法,只要它能够搜索正则表达式。搜索与您要交换的所有单词匹配的正则表达式,例如
狗|猫|老鼠|老鼠
。为结果维护一个单独的字符串(在许多语言中,这需要是某种类型的
StringBuilder
,以便重复追加以加快速度),最初为空。对于每个匹配,您将在上一个匹配的结尾(或字符串的开头)和当前匹配之间添加字符,然后将适当的替换项(可能从hashmap获得)添加到结果中


大多数标准库应该允许您使用内置方法轻松地完成这项工作。有关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
}
for(int i=0;i<句子长度;i++){
如果(句子[i]。等于(“猫”){
“狗”一句;
}
//更相似的if语句
}

现在
句子[]
包含带单词的新句子。一些正则表达式魔术应该允许您也保留标点符号。我希望这有帮助,请告诉我是否有什么可以改进的地方。

在tcl中,这可以使用函数
string map
一次性完成。例如:
string map{猫狗老鼠}$text
啊,这个解决方案似乎非常方便。如果您的语言支持它。我过去使用的一个技巧是使用不可打印的字符作为临时字符串:
\0
\1
\2
等。OP和@slebetman:除非您100%确定可以控制字符串中的内容,否则这个解决方案会自找麻烦如果字符串是用户提供的(甚至是系统在您无法完全控制的系统的某个部分中生成的),则您选择的字符将在某个时候出现在输入字符串中,并造成严重破坏。