Replace multiple strings with multiple other strings

Anderson Green picture Anderson Green · Mar 24, 2013 · Viewed 255.7k times · Source

I'm trying to replace multiple words in a string with multiple other words. The string is "I have a cat, a dog, and a goat."

However, this does not produce "I have a dog, a goat, and a cat", but instead it produces "I have a cat, a cat, and a cat". Is it possible to replace multiple strings with multiple other strings at the same time in JavaScript, so that the correct result will be produced?

var str = "I have a cat, a dog, and a goat.";
str = str.replace(/cat/gi, "dog");
str = str.replace(/dog/gi, "goat");
str = str.replace(/goat/gi, "cat");

//this produces "I have a cat, a cat, and a cat"
//but I wanted to produce the string "I have a dog, a goat, and a cat".

Answer

Ben McCormick picture Ben McCormick · Mar 24, 2013

Specific Solution

You can use a function to replace each one.

var str = "I have a cat, a dog, and a goat.";
var mapObj = {
   cat:"dog",
   dog:"goat",
   goat:"cat"
};
str = str.replace(/cat|dog|goat/gi, function(matched){
  return mapObj[matched];
});

jsfiddle example

Generalizing it

If you want to dynamically maintain the regex and just add future exchanges to the map, you can do this

new RegExp(Object.keys(mapObj).join("|"),"gi"); 

to generate the regex. So then it would look like this

var mapObj = {cat:"dog",dog:"goat",goat:"cat"};

var re = new RegExp(Object.keys(mapObj).join("|"),"gi");
str = str.replace(re, function(matched){
  return mapObj[matched];
});

And to add or change any more replacements you could just edit the map. 

fiddle with dynamic regex

Making it Reusable

If you want this to be a general pattern you could pull this out to a function like this

function replaceAll(str,mapObj){
    var re = new RegExp(Object.keys(mapObj).join("|"),"gi");

    return str.replace(re, function(matched){
        return mapObj[matched.toLowerCase()];
    });
}

So then you could just pass the str and a map of the replacements you want to the function and it would return the transformed string.

fiddle with function

To ensure Object.keys works in older browsers, add a polyfill eg from MDN or Es5.