1

I'm trying to write a javascript function that replaces certain characters in a string. For example, if I want to replace 'a' with 'ab' and 'b' with 'c' in the string "a b", the function should give me the string "ab c". In this case I can't just run a replace with 'a' on the string first and then another replace with 'b' on the result because that would give me "ac b" instead of "ab c".

Any ideas on how to efficiently do this?

4
  • 1
    So, the problem with the function (as you imagine it to run) is that it does, or will do, what you tell it to do? Is there an underlying problem that you're trying to solve? Commented Jun 5, 2013 at 6:56
  • yes , exactly what you need: developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/… Commented Jun 5, 2013 at 6:56
  • 1
    could you try "a b".split('').map( function( v ){ return v.replace('b', 'c').replace('a','ab'); }).join('') Commented Jun 5, 2013 at 7:10
  • @shoopdelang added as answer Commented Jun 5, 2013 at 8:24

3 Answers 3

5

You can use a regular expression to match the different characters, and a callback function to determine what to replace it with. As it does all replacements in one run, there is no problem with one replacement containing another thing to replace:

s = s.replace(/[ab]/g, function(m){
  switch (m) {
    case 'a': return 'ab';
    case 'b': return 'c';
  }
  return m;
});

Demo: http://jsfiddle.net/Guffa/pXSM5/

Edit:

To use regular expressions for matching each string, loop through them and find every match, then loop through the found matches and replace them. It's easiest to do the replacements starting with the last one in the string, that way you don't have to adjust the index of other matches when a replacement has a different length from the matched string:

var s = "a b";
var re = [{ regex: /a/g, replace: 'ab'}, { regex: /b/g, replace: 'c' }];
var pos = [];

for (var i = 0; i < re.length; i++) {
    while ((r = re[i].regex.exec(s)) != null) {
        pos.push({ index: r.index, match: r[0], replace: re[i].replace });
    }
}

while (pos.length > 0) {
    var last = 0;
    for (var i = 0; i < pos.length; i++) {
        if (pos[i].index > pos[last].index) last = i;
    }
    var p = pos[last];
    s = s.substr(0, p.index) + p.replace + s.substr(p.index + p.match.length);
    pos.splice(last, 1);
}

Demo: http://jsfiddle.net/Guffa/pXSM5/1/

Note: Make sure that the regular expressions doesn't match anything that can overlap.

Sign up to request clarification or add additional context in comments.

2 Comments

Ok I was thinking something along those lines. Actually the function I'm trying to write is a bit more complicated. It takes in a set of regular expressions and replaces each regex match with a certain string. That means I can't simply have a switch statement in the callback since I'm not looking for constant strings. I suppose I could do more regexs in the callback but that seems a bit inefficient.
@shoopdelang: Well, that should teach you not to simplify the question too much. ;) I added a solution for that too above.
0

The correct solution: regular expressions. The "downside" is that it's difficult to learn, (but once you learn, it's totally worth).

A "quick" solution is this:

  1. replace a with something extremely unusual ("unique") and which must not contain "b"
  2. replace b with whatever you want
  3. replace the extremely unusual with ab

like this

a -> <my_unique_replacement_which_does_not_contain_the_letter_____you_know!>
b -> c
<my_unique_replacement_which_does_not_contain_the_letter_____you_know!> -> ab

it's not guaranteed, it's not a 100% solution to use everywhere, but it is a quick fix for limited use.

Comments

0

I made small code using array split and replace

var s = "a b ba c",
    re = [['a','ab'], ['b','c'], ['c','d']] ;

var replaced = s.split('').map( function( v ){

    var found = false,
        once = function( c ){
            return function( v ){             
                return found? v: ( found = true && c ) ;
            }
        };

    return re.reduce( function ( a, p ){
        return a.replace( p[0], once( p[1]) ); 
    }, v );

}).join('');

console.log( replaced );

and replaced has output ab c cab d

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.