views:

594

answers:

3

Hi all

see my code snippet below:

var list = ['one', 'two', 'three', 'four'];
var str = 'one two, one three, one four, one';
for ( var i = 0; i < list.length; i++)
{
     if (str.endsWith(list[i])
     {
         str = str.replace(list[i], 'finsih')
     }
 }

I want to replace the last occurence of the word one with the word finish in the string, what I have will not work because the replace method will only replace the first occurence of it. Does anyone know how I can amend that snippet so that it only replaces the last instance of 'one'

Thank you Ruth

+2  A: 

Well, if the string really ends with the pattern, you could do this:

str = str.replace(new RegExp(list[i] + '$'), 'finish');
Pointy
Good idea. Need to escape that string first (though not with her sample data, granted), which is non-trivial. :-(
T.J. Crowder
Thank You very much
Ruth
@Ruth no prob! @TJ yes, indeed that's true: Ruth if you end up with "words" you're looking for that include the special characters used for regular expressions, you'd need to "escape" those, which as TJ says is a little tricky (not impossible though).
Pointy
+2  A: 

You can use String#lastIndexOf to find the last occurrence of the word, and then String#substring and concatenation to build the replacement string.

n = str.lastIndexOf(list[i]);
if (n >= 0 && n + list[i].length >= str.length) {
    str = str.substring(0, n) + "finish";
}

...or along those lines.

T.J. Crowder
Thank You very much
Ruth
+1  A: 

I know this is silly, but I'm feeling creative this morning:

'one two, one three, one four, one'
.split(' ') // array: ["one", "two,", "one", "three,", "one", "four,", "one"]
.reverse() // array: ["one", "four,", "one", "three,", "one", "two,", "one"]
.join(' ') // string: "one four, one three, one two, one"
.replace(/one/, 'finish') // string: "finish four, one three, one two, one"
.split(' ') // array: ["finish", "four,", "one", "three,", "one", "two,", "one"]
.reverse() // array: ["one", "two,", "one", "three,", "one", "four,", "finish"]
.join(' '); // final string: "one two, one three, one four, finish"

So really, all you'd need to do is add this function to the String prototype:

String.prototype.replaceLast = function (what, replacement) {
    return this.split(' ').reverse().join(' ').replace(new RegExp(what), replacement).split(' ').reverse().join(' ');
};

Then run it like so: str = str.replaceLast('one', 'finish');

One limitation you should know is that, since the function is splitting by space, you probably can't find/replace anything with a space.

Actually, now that I think of it, you could get around the 'space' problem by splitting with an empty token.

String.prototype.reverse = function () {
    return this.split('').reverse().join('');
};

String.prototype.replaceLast = function (what, replacement) {
    return this.reverse().replace(new RegExp(what.reverse()), replacement.reverse()).reverse();
};

str = str.replaceLast('one', 'finish');
Matt
Thank You very much
Ruth