6

I am trying to swap all occurrences of a pair of substrings within a given string.

For example, I may want to replace all occurrences of "coffee" with "tea" and all occurrences of "tea" with "coffee".

This is the first thing I thought of:

var newString = oldString.replace(/coffee/g, "__").replace(/tea/g, "coffee").replace(/__/g, "tea");

It works most of the time, but if my input string contains the substring "__", it will not work properly.

I am looking for something that works regardless of what input I give it, so I thought some more and came up with this:

var pieces = oldString.split("coffee");
for (var i = 0; i < pieces.length; i++)
  pieces[i] = pieces[i].replace(/tea/g, "coffee");
var newString = pieces.join("tea");

It works fine but it is kind of ugly and verbose. I tried to come up with something more concise and I used the map function built into jQuery to come up with this:

var newString = $.map(oldString.split("coffee"), function(piece) {
  return piece.replace(/tea/g, "coffee");
}).join("tea");

That is better but I still have a feeling that there is some brilliantly simple method that is failing to come to my mind. Does anyone here know a simpler way?

Stephen
  • 1,607
  • 2
  • 18
  • 40
Elias Zamaria
  • 96,623
  • 33
  • 114
  • 148

5 Answers5

8

What about

theString.replace(/(coffee|tea)/g, function($1) {
     return $1 === 'coffee' ? 'tea' : 'coffee';
});

(Personally I think it's a crime to swap coffee and tea, but that's your business)

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
Alexander Gessler
  • 45,603
  • 7
  • 82
  • 122
  • be careful if one of the strings is a substring of the other. put the longer one first. (and obviously escape any special characters) – Patrick Parker Mar 07 '19 at 06:31
2

You can use a function:

var str = "I like coffee more than I like tea";
var newStr = str.replace(/(coffee|tea)/g, function(x) {
   return x === "coffee" ? "tea" : "coffee";
});
alert(newStr); 

Running example

Elias Zamaria
  • 96,623
  • 33
  • 114
  • 148
epascarello
  • 204,599
  • 20
  • 195
  • 236
0

Based on @alexander-gessler's answer, but with support for dynamic inputs.

(While potentially opening the door to code injection.)

function swapSubstrings(string, a, b) {
  return string.replace(
    new RegExp(`(${a}|${b})`, "g"),
    match => match === a ? b : a
  )
}
Arye Eidelman
  • 1,579
  • 16
  • 22
0

Close. Consider this:

var newString = oldString.replace("tea|coffee", function(match) {
    // now return the right one, just a simple conditional will do :)
});

Happy coding.

0

Use a map (an object) to define what replaces what and then a function to tap into the map:

D:\MiLu\Dev\JavaScript :: type replace.js
function echo(s) { WScript.Echo(s) }
var
map = { coffee: "tea", tea: "coffee" },
str = "black tea, green tea, ice tea, teasing peas and coffee beans";
echo( str.replace( /\b(tea|coffee)\b/g, function (s) { return map[s] } ) );

D:\MiLu\Dev\JavaScript :: cscript replace.js
black coffee, green coffee, ice coffee, teasing peas and tea beans
Lumi
  • 14,775
  • 8
  • 59
  • 92