Alex
Alex

Reputation: 2959

How to replace from regex with random value at each occurrence?

I have this kind of sentences:

var str = 'The <adjective> <noun> and <noun> <title>';

I would like to replace each <pattern> by a random value from their related array.

In my previous example I'd like to get something similar to:

var adjectives = ['big' 'small' 'funny'];
var nouns = ['dog', 'horse', 'ship'];
var title = ['bar', 'pub', 'club'];

var str = 'The <adjective> <noun> and <noun> <title>';
var r = str.replacePatterns({ noun: nouns, adjective: adjectives, title: titles });
console.log(r); // The big horse and ship club

I almost get it by didn't tough about same pattern (e. g. <noun>) twice in the same sentence. So I generate only one random value for each pattern...

String.prototype.replacePatterns = function (hash) {

    var string = this,
        key;

    for (key in hash) {
        if (hash.hasOwnProperty(key)) {
            var randomValue = hash[key][Math.floor(Math.random() * hash[key].length)];
            string = string.replace(new RegExp('\\<' + key + '\\>', 'gm'), randomValue);
        }
    }

    return string;
};

Could you help me to get something replacing each pattern by a random value instead of a global replacement?

I don't know how to loop result of a regex to replace the matches in the original sentence (with random value each time).

Upvotes: 3

Views: 2869

Answers (2)

Damon
Damon

Reputation: 4336

You can also use a regex instead of looping. Something like

function replacePatterns(str, options) {
  options = options || {
    adjective: ['big', 'small', 'funny'],
    noun: ['dog', 'horse', 'ship'],
    title: ['bar', 'pub', 'club']
  }

  return str.replace(/<(.*?)>/g, function(match) {
    match = match.replace(/<|>/g,'')
    return options[match][Math.floor(Math.random()*options[match].length)]
  })
}

Also added in the optional options hash for added flexibility.

Upvotes: 2

T.J. Crowder
T.J. Crowder

Reputation: 1074495

replace accepts a function as its second argument, which is called for each replacement and can return the value to replace with. So use a function and move the random number generation into it:

String.prototype.replacePatterns = function (hash) {

    var string = this,
        key,
        entry;

    for (key in hash) {
        if (hash.hasOwnProperty(key)) {
            entry = hash[key]
            string = string.replace(new RegExp('\\<' + key + '\\>', 'gm'), function() {
                return entry[Math.floor(Math.random() * entry.length)]
            });
        }
    }

    return string;
};

You don't need it here, but just FYI, the function receives the matched text as its first argument, and if you have capture groups in your regular expression (you don't), it receives them as subsequent arguments. Details in the MDN page for String#replace or, of course, the spec.

Upvotes: 3

Related Questions