views:

50

answers:

3

I have a whole array of regexp queries to make recursively going through the string in order.

Is there a way I can do it all with 1 call such as (doesn't work)?

str.replace(/query1|query2|query3|query4|...|[0-9]+|[^]/,
             "reslt1|reslt2|reslt3|reslt4|...|procNumb|procChar");

It need only work in Firefox. Right now I'm stuck with:

str.replace(... ,function(a,b,c){if (a=="query1") return "reslt1"; ..............});

Thanks!

Edit: Sorry if confusing. Goal:

Before: "query1query3x123query2" After: "reslt1reslt3procChar(x)procNumb(123)reslt2"

The main thing is I need I to process the string 1 fragment at a time recursively, so I think I must use a super-query like that to match any, or not use regexes at all. I just wonder if there's a way to automatically pair the results to the queries when using lots of pipes. I am not so familiar with javascript regex but I couldn't find anything on mdc unfortunately.

A: 

Why don't you just run them one by one in a loop like so:

for (var i = 0; i < regexes.length; i++) {
    str = str.replace(regexes.regex, regexes.result);
}

It's easy to understand, more or less easy to maintain, and probably faster than one huge query. Those alternatives in regex come to a huge price.

vava
A: 

Assuming you want to replace query1 with reslt1, query2 with reslt2, and so on, I don't think that can be done using a single regex. However, it's fairly simply using an Nx2 array (or an object, but the definition of such would be more verbose):

var repl_table = [[/query1/g, 'reslt1'],
                  [/query2/g, 'reslt2'],
                  [/query3/g, 'reslt3'],
                  [/query4/g, 'reslt4'],
                  [/([0-9]+)/g, 'procNumb($1)'],
                  [/([^])/g, 'procChar($1)']]

function repl(s, table) {
  for (var i=0; i<table.length; i++) {
    s = s.replace(table[i][0], table[i][1]);
  }
  return s;
}

// Then call:
result = repl(source, repl_table);
Max Shawabkeh
A: 

If you're trying to match any of several alternative substrings and provide a different result for each match, you're going to have to use a function (as you appear to be doing). For instance:

var str = "ABCDE";

str = str.replace(/A|B|C|D/g, function(match) {
    var rv;
    switch (match)
    {
        case 'A':
            rv = '1';
            break;
        case 'B':
            rv = '2';
            break;
        case 'C':
            rv = '3';
            break;
        case 'D':
            rv = '4';
            break;
    }
    return rv;
});
alert(str); // Alerts 1234E

(Of course, that particular example would be better done as an array lookup.)

If you're a vertical brevity fiend (I'm not, but some are), you can use early returns:

str = str.replace(/A|B|C|D/g, function(match) {
    switch (match)
    {
        case 'A': return '1';
        case 'B': return '2';
        case 'C': return '3';
        case 'D': return '4';
    }
});
alert(str); // Alerts 1234E

Edit Just to be clear, about my "array lookup" comment above: If the replacements really are just a static lookup, you can do this:

var str, replacements, key, rex;

// Potentially one-time prep, if you're re-using this lookup
replacements = {
    "A": "1",
    "B": "2",
    "C": "3",
    "D": "4"
};
rex = [];
for (key in replacements)
{
    rex.push(key);
}
rex = new RegExp(rex.join('|'), "g");

// The bit you reuse
str = "ABCDE";
str = str.replace(rex, function(match) {
    return replacements[match];
});
alert(str); // Alerts 1234E

...since JavaScript objects are associative arrays.

T.J. Crowder
Regarding "If you're a vertical brevity fiend" - you can't seriously say that the first example is more readable than the second, can you?
Max Shawabkeh
I despise all whitespace, I guess I'd do this then (the second style :P), I was just dreaming of a more concise way to write it. Formatting in the replacement string... makes sense.
@Max: I find it *as* readable, at least; not less, not more. Trivial examples like the above form a poor basis for debates of readability. :-) You wouldn't do it that way anyway, at least not in JavaScript; you'd use an object (associative array) lookup. But for anything even slightly more complex, I'd absolutely do it the first way. One of the usual maintainability guidelines is to have a single return from a function. It's not a guideline I always follow, but generally, yeah. It makes debugging easier, makes the function less fragile when being enhanced, etc.
T.J. Crowder