4
x.replace(/old/gi. 'new');
x.replace(/whatever/gi. 'whatevernew');
x.replace(/car/gi. 'boat');

Is there a way to combine those in one regexp statement perhaps and array of old and new words. PHP solution is also welcome.

Pinkie
  • 10,126
  • 22
  • 78
  • 124
  • 2
    i think you will have good use of this [LINK](http://stackoverflow.com/questions/2473774/javascript-replace-with-callback-performance-question) – Ibu Jun 30 '11 at 03:53

6 Answers6

2

You could do something like this:

var x = 'The old car is just whatever';
var arr = [{ old: /old/gi, new: 'new' },
           { old: /whatever/gi, new: 'whatevernew' },
           { old: /car/gi, new: 'boat' }];

for (var ii = 0; ii < arr.length; ii++) {
    x = x.replace(arr[ii].old, arr[ii].new);
}
FishBasketGordo
  • 22,904
  • 4
  • 58
  • 91
  • Actually, you do need a regex just to replace word. This code will will only replace each word once, and is case sensitive. You want `x.raplace(new RegExp(arr[ii].old, 'gi'), arr[ii].new)`. – Kobi Jun 30 '11 at 04:07
2

lbu and RobG present an interesting approach using the callback. Here's a little more general purpose version of that where you have a function that just takes a data structure of what you want to replace and what you want to replace it with as a parameter.

function multiReplace(str, params) {
    var regStr = "";
    for (var i in params) {
        regStr += "(" + i + ")|";    // build regEx string
    }
    regStr = regStr.slice(0, -1);   // remove extra trailing |
    return(str.replace(new RegExp(regStr, "gi"), function(a) {
        return(params[a]);
    }));
}


var test = 'This old car is just whatever and really old';
var replaceParam = {"old": "new", "whatever": "something", "car": "boat"};

var result = multiReplace(test, replaceParam);
alert(result);

And a fiddle that shows it in action: http://jsfiddle.net/jfriend00/p8wKH/

jfriend00
  • 683,504
  • 96
  • 985
  • 979
1

Try this:

var regexes = { 'new': /old/gi, 'whatevernew': /whatever/gi, 'boat': /car/gi };

$.each(regexes, function(newone, regex){
  x = x.replace(regex, newone);
});

Or this:

var regexes = { 'old':'new', 'whatever':'whatevernew', 'car':'boat'};

$.each(regexes, function(oldone, newone){
  x = x.replace(new RegExp(oldone, 'gi'), newone);
});
Sanghyun Lee
  • 21,644
  • 19
  • 100
  • 126
  • 1
    The problem here is that the order isn't defined: it's possible `whatever` and `new` will be replaced before `whatevernew`, so you may get different results in different iterations (or at least different browsers) – Kobi Jun 30 '11 at 04:09
  • @Kobi I think it'll process sequentially. I couldn't find any resource about `jQuery.each()`'s order. Do you have one? – Sanghyun Lee Jun 30 '11 at 04:24
  • This one, for example: http://stackoverflow.com/questions/242841#243778 , or this: https://developer.mozilla.org/en/JavaScript/Reference/Statements/for...in#Description . It isn't specific to `jQuery.each`: there is no order among object properties. It doesn't matter how `jQuery.each` is implemented, you cannot rely on the definition of the variable `regexes`. The order in which you wrote the properties isn't guaranteed to be kept internally. – Kobi Jun 30 '11 at 04:38
1

the replace method supports using a a call back function:

var x = 'This old car is just whatever';
var y = x.replace(/(old)|(whatever)|(car)/gi,function (a) {
    var str = "";

    switch(a){
      case "old":
         str = "new";
         break;
      case "whatever":
         str = "something";
         break;
      case "car":
         str = "boat";
         break;
      default: 
         str= "";
    }
    return str;
});
alert(y);

// Y will print "This new car is just something"
Ibu
  • 42,752
  • 13
  • 76
  • 103
1

Here's a couple more:

// Multi RegExp version
var replaceSeveral = (function() {
  var data = {old:'new', whatever: 'whatevernew', car: 'boat'};

  return function(s) {
    var re;
    for (var p in data) {
      if (data.hasOwnProperty(p)) {
        re = new RegExp('(^|\\b)' + p + '(\\b|$)','ig');
        s = s.replace(re, '$1' + data[p] + '$2');
      }
    }
    return s;
  }
}());

// Replace function version
var comparitor = (function() {
  var data = {old:'new', whatever: 'whatevernew', car: 'boat'};
  return function (word) {
    return data.hasOwnProperty(word.toLowerCase())? data[word] : word;
  }
}());


var s = 'old this old whatever is a car';
alert(
  s 
  + '\n' + replaceSeveral(s)
  + '\n' + s.replace(/\w+/ig, comparitor)

);
RobG
  • 142,382
  • 31
  • 172
  • 209
1

Ibu's callback solution is pretty clean, but can be further streamlined:

x = x.replace(/\b(?:old|whatever|car)\b/gi,
        function (m0) {
            return {'old': 'new',
                    'car': 'boat',
                    'whatever': 'something'}[m0];
        });

This technique of using an object literal is quite efficient. I modified the regex to match only whole words by adding word boundaries (to avoid changing gold to gnew etc).

EDIT: Upon closer inspection, I see that jfriend00's solution is using the same technique (and is generalized to be more useful).

ridgerunner
  • 33,777
  • 5
  • 57
  • 69
  • Looking a all the solutions provided, it seem like my original code is allot shorter and more efficient then most of the answers provided here. +1 for the efforts – Pinkie Jul 01 '11 at 05:40