简体   繁体   中英

JavaScript - From an optimization standpoint how should one replace multiple substrings in a string with different strings?

In the code that I develop and maintain I have ran into an issue.

I have a function that takes a query (type string) and replaces substrings of that string with a different string. As an example if a user types in the string I have a cat it would replace it with I have a dog .

My code works but the problem is I have hundreds of such substrings that need to be replaced with a different one. It also looks really bad aesthetically.

var myString;
myString = myString.replace('cat','dog')
                   .replace('elephant','zebra')
                   .replace('bird','fish')
                   // Goes on for hundreds of lines

This is all inside a function in which everytime it's called it goes through hundreds of replace calls.

One thing I could try doing is creating an array of objects and iterating through it. The code would look something like this.

var animalsArray = [
                       {'a':'cat','b':'dog'},
                       {'a':'elephant','b':'zebra'},
                       {'a':'bird','b':'fish'}
                   ];

And then in my function

function stringReplace(string) {
    for (var i = 0; i < animalsArray.length; i++) {
        if (string.indexOf(animalsArray[i]['a']) > -1) {
            sting = string.replace(animalsArray[i]['a'],animalsArray[i]['b']);
        }
    }
}

But I'm not sure whether that would improve on my current practice of chaining together hundreds of replace calls.

I'm basically looking to optimize my current code. What is the best practice?

You can make a regaulr expression with a bunch of or statements. (dog|elephant|bird|....) and that will allow you to run one check. The replace gives you the matched text which you can use to look up the word to replace.

So make an object of the strings to replace and their value is the word to replace. You can just look up the replacement by the matched key.

 const animals = { cat: 'dog', elephant: 'zebra', bird: 'fish', } // build the or sting with a simple join const keysString = Object.keys(animals).join("|") // generate the regular expression to match the words var animalRE = new RegExp(`\\\\b(${keysString})\\\\b`,'g'); // a sample string to match const myString = "I like to pet a cat that looks like an elephant that moves like a bird." // the replacement step. The function takes the matched text (aka key) and looks it up in the object const updated = myString.replace(animalRE, key => animals[key] || key) // display the new string console.log(updated)

I'd consider using an object instead, whose keys are the substrings to be replaced, and whose values are the replacements. Make a regular expression by alternating all of the object's keys, then use a replacer function to look up the associated value on the object:

 const replacements = { cat: 'dog', elephant: 'zebra', bird: 'fish' }; const pattern = new RegExp(Object.keys(replacements).join('|'), 'g'); console.log('Foo cat bar bird'.replace(pattern, match => replacements[match]));

Using object syntax makes it easy to add/remove items. If you want to make it even easier to modify, you could consider putting the replacement information into a string instead, then parsing it into an object:

 const replacementsStr = ` cat dog elephant zebra bird fish `; const replacements = Object.fromEntries( replacementsStr .trim() .split('\\n') .map(line => line.split(/\\s+/)) ); const pattern = new RegExp(Object.keys(replacements).join('|'), 'g'); console.log('Foo cat bar bird'.replace(pattern, match => replacements[match]));

I would do something like:

 function WordSwapper(sentence){ const swapper = sentence; this.swaps = []; this.add = (word, replacer)=>{ this.swaps.push([word, replacer]); return this; } this.swap = (sentence = null)=>{ let s = sentence === null ? swapper : sentence; this.swaps.forEach(a=>{ s = s.replace(new RegExp(a[0], 'gi'), a[1]); }); return s; } } const ws = new WordSwapper('The cat plays. Elephants live in the Serengeti. Have you ever seen a bird fly?'); ws.add('cat', 'dog').add('elephant', 'zebra').add('bird', 'fish'); console.log(ws.swap());

Of course, you may want to do something with plural and uppercase situations.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM