Giorgio L
Giorgio L

Reputation: 75

Javascript regex replace with different values

I'd like to know if it is possible to replace every matching pattern in the string with not one but different values each time.

Let's say I found 5 matches in a text and I want to replace first match with a string, second match with another string, third match with another and so on... is it achievable?

var synonyms = ["extremely", "exceedingly", "exceptionally", "especially", "tremendously"];

"I'm very upset, very distress, very agitated, very annoyed and very pissed".replace(/very/g, function() {
//replace 5 matches of the keyword every with 5 synonyms in the array
});

Upvotes: 4

Views: 3209

Answers (6)

Peter Seliger
Peter Seliger

Reputation: 13377

function replaceExpressionWithSynonymsInText(text, regX, synonymList) {
    var
        list = [];

    function getSynonym() {
        if (list.length <= 0) {
            list = Array.from(synonymList);
        }
        return list.shift();
    }
    return text.replace(regX, getSynonym);
}

var
    synonymList = ["extremely", "exceedingly", "exceptionally", "especially", "tremendously"],
    textSource  = "I'm very upset, very distress, very agitated, very annoyed and very pissed",

    finalText   = replaceExpressionWithSynonymsInText(textSource, (/very/g), synonymList);

console.log("synonymList : ", synonymList);
console.log("textSource : ", textSource);
console.log("finalText : ", finalText);

The advantages of the above approach are, firstly one does not alter the list of synonyms, secondly working internally with an ever new copy of the provided list and shifting it, makes additional counters obsolete and also provides the opportunity of being able to shuffle the new copy (once it has been emptied), thus achieving a more random replacement.

Upvotes: 1

Josh
Josh

Reputation: 4806

A simple recursive approach. Be sure your synonyms array has enough elements to cover all matches in your string.

let synonyms = ["extremely", "exceedingly", "exceptionally"]
let yourString = "I'm very happy, very joyful, and very handsome."
let rex = /very/

function r (s, i) {
    let newStr = s.replace(rex, synonyms[i])
    if (newStr === s)
        return s
    return r(newStr, i+1)
}

r(yourString, 0)

I would caution that if your replacement would also match your regex, you need to add an additional check.

Upvotes: 1

casual
casual

Reputation: 129

You can do it with the use of Replace() function, where you use 'g' option for global matching (finds all occurrences of searched expression). For the second argument you can use a function which returns values from your predefined array.

Here is a little fiddle where you can try it out.

var str = "test test test";
var rep = ["one", "two", "three"];
var ix = 0;
var res = str.replace(/test/g, function() {
  if (ix == rep.length)
    ix = 0;
  return rep[ix++];
});
$("#result").text(res);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id="result">
  Result...
</p>

Upvotes: 0

Michael Russo
Michael Russo

Reputation: 442

Using the example you've provided, here's what I would do.

First I would set up some variables

var text = "I'm very upset, very distress, very agitated, very annoyed and very pissed";
var regex = /very/;
var synonyms = ["extremely", "exceedingly", "exceptionally", "especially", "tremendously"];

Then count the number of matches

var count = text.match(/very/g).length;

Then I would run a loop to replace the matches with the values from the array

for(var x = 0; x < count; x++) {
    text = text.replace(regex, synonyms[x]);
}

Upvotes: 0

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626927

You may try to replace the matches inside a replace callback function:

var synonyms = ["extremely", "exceedingly", "exceptionally", "especially", "tremendously"];
var cnt = 0;
console.log("I'm very upset, very distress, very agitated, very annoyed and very pissed (and very anxious)".replace(/very/g, function($0) {
  if (cnt === synonyms.length) cnt = 0;
  return synonyms[cnt++]; //replace 5 matches of the keyword every with 5 synonyms in the array
}));

If you have more matches than there are items in the array, the cnt will make sure the array items will be used from the first one again.

Upvotes: 7

NiceNix
NiceNix

Reputation: 151

Yes it is achievable. There may be a more efficient answer than this, but the brute force way is to double the length of your regex. i.e. Instead of searching just A, search (/A){optionalText}(/A) and then replace /1 /2 as needed. If you need help with the regex itself, provide some code for what you're searching for and someone with more rep than me can probably comment the actual regexp.

Upvotes: -1

Related Questions