views:

54

answers:

3

I want to take strings like:

  • Submit Changes
  • Create New
  • Update Record
  • Save Item

and convert them to:

  • Submitting Changes
  • Creating New
  • Updating Record
  • Saving Item

with a function like:

var ConvertToProgressivePresent = (function(){
    // cache this regex
    var rProgressivePresent = /\b(?:(Submi(t))|(Creat|Sav|Updat)e)\b/i;
    return function(phrase){
        return phrase.replace(rProgressivePresent, "$1$2$3ing");
    };
}());

This above regex works but doesn't seem like the best way to do it. I don't like the grouping here where 1-2 groups are always empty when there is a match.

Got any suggestions or improvements?

+1  A: 

I think you should probablly use CASE statments instead. Regex isn't the most efficient way of doing things...and that is probably best that it doesn't cuz you know the old saying.

Wow, I have this problem...I know, I'll use regex...ok, now you have two problems 90)

Keng
I second that. It will be much easier to add an extra case statement than to hack it in the regex.
skazhy
Hm, can you demonstrate a good way to do this with a `switch`/`case`? `if-else-if` seems like it would be better than `case` for this.
David Murdoch
I'm not really a java guy but couldn't you do it like this one? http://stackoverflow.com/questions/3290550/javascript-switch-case
Keng
haha. No you are not. You are probably not much of a Javascript guy eithe. :-p They are VERY different languages.
David Murdoch
@David Murdoch HA!! nor am I much of a "interupt me while I'm posting a comment on SO" guy either 80))
Keng
A: 

First off, it doesn't appear to me that your regex does quite what you want anyway in that I don't see a second "t" added when changing submit to submitting.

However, I don't think I would use regex for this task at all anyway. If you are just trying to replace one word with another, and the word always comes at the beginning of the string, I might do something like:

function ReplaceIfBeginsWith(wholeString, checkFor, replaceWith)
{
    if (wholeString.indexOf(checkFor + ' ') == 0)
    {
        return replaceWith + ' ' + wholeString.substr(checkFor.length + 1);
    }
    if (wholeString == checkFor)
    {
        return replaceWith;
    }
    return wholeString;
}

Then, you can call the function with each of the words you would want to replace. If you want case-insensitivity, just check against lowercase versions of all the strings.

Andrew
Not Exactly the right approach for my case. Thanks though.
David Murdoch
The second "t" does get added, BTW.
David Murdoch
+2  A: 

If you have specific words to replace with then you could make a word bank. Have the words and their replacement stored in an object and then loop through it.

var ConvertToProgressivePresent = (function() {
    var replaceValues = {
        "Submit": "Submitting",
        "Create": "Creating",
        "Update": "Updating",
        "Save": "Saving"
    }
    return function(phrase) {
        for (var item in replaceValues) {
            phrase = phrase.replace(item, replaceValues[item]);
        }
        return phrase;
    };
}());

Here is a JSFiddle Example

subhaze
Nicely done. I'd probably use arrays instead of the hash though. Now how would you go about case-insensitivity; surely you wouldn't add more words to the bank?
David Murdoch
Here is an update that is case-insensitive http://www.jsfiddle.net/subhaze/aVnhH/3/
subhaze
Cool. But what happens with the string "Submit Your Update"? It should only change the FIRST match.
David Murdoch
Heres a test suite(ish): http://jsfiddle.net/3hJD5/ and benchmark: http://jsperf.com/regex-vs-bank-regex
David Murdoch
Made an update to the Fiddle you made, this version passes all tests. http://jsfiddle.net/3hJD5/1/
subhaze
Actually I should have used the "match" var in the above example instead of "phrase" var: http://jsfiddle.net/3hJD5/2/
subhaze