4

I have a JS string that needs several of its chars replaced.

For example, for input string:

s = 'ABAC'

I would want to replace all Bs with Cs and vice versa. However, doing a standard regex replace is not good enough since the replace()s should not occur in lockstep but rather in a single pass on the string.

>>> s.replace(/B/g, 'C').replace(/C/g, 'B')
'ABAB' // not good

Is there an elegant way to do multiple string replace() in a single pass?

(Solution must work for any arbitrary char replacement)

Yuval Adam
  • 161,610
  • 92
  • 305
  • 395

3 Answers3

9
var str = 'ABACACCBA',
    out = str.replace(/[CB]/g, function(c) {
        return {
            "B" : "C",
            "C" : "B"
        }[c];
    });

console.log(out);  /* ACABABBCA */

all you have to do is to define all characters to match and then an object with swapping rules. An alternative can be also done in this way

var str = 'ABACACCBA',
    out = str.replace(/\w/g, function(c) {
        return {
            "B" : "C",
            "C" : "B"
        }[c] || c;
    });

console.log(out);  /* ACABABBCA */

in this example you execute the function for every character matched, but you make a swap only if you defined an entry into the object (otherwise you return the original character).

It's clearly more expensive (so better use the first example) but in this case you avoid to list all characters to match in the regular expression.

Fabrizio Calderan
  • 120,726
  • 26
  • 164
  • 177
0

You want a translate function; see this question for an example implementation.

Community
  • 1
  • 1
beerbajay
  • 19,652
  • 6
  • 58
  • 75
  • Not sure I understood the examples given there. In any case, it seems much more complicated than what I need (see accepted answer). Might be userful for other cases though, thanks. – Yuval Adam Mar 02 '12 at 15:24
0

There may well be neater ways to do it, but I usually do something simple like this....

s.replace(/B/g, '##_B_##').replace(/C/g, 'B').replace(/##_B_##/g, 'C');

Basically, make the Bs unique before replacing C with B so that the original Bs can still be identified.

Reinstate Monica Cellio
  • 25,975
  • 6
  • 51
  • 67
  • This isn't good enough for arbitrary replacements. Your solution requires building a dependency graph of the char replacements. Not an elegant solution. – Yuval Adam Mar 02 '12 at 15:16
  • I don't know the content of s so I can't suggest anything more unique to use. It's a simple approach but I've used it for a long time and never had issues with it. Hope you find something better :) – Reinstate Monica Cellio Mar 02 '12 at 15:17
  • I'm saying that this solution isn't generic. Sure, if I only need to translate `B <-> C` then I can do this. The point is that I do not know *a priori* which chars I need to replace. – Yuval Adam Mar 02 '12 at 15:20
  • Perhaps you should update your question to reflect that then as it will make a big difference. – Reinstate Monica Cellio Mar 02 '12 at 15:25