JavaScript: replace last occurrence of text in a string
JavascriptStringReplaceJavascript Problem Overview
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], 'finish')
}
}
I want to replace the last occurrence 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 occurrence of it. Does anyone know how I can amend that snippet so that it only replaces the last instance of 'one'
Javascript Solutions
Solution 1 - Javascript
Well, if the string really ends with the pattern, you could do this:
str = str.replace(new RegExp(list[i] + '$'), 'finish');
Solution 2 - Javascript
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.
Solution 3 - Javascript
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');
Solution 4 - Javascript
Not as elegant as the regex answers above, but easier to follow for the not-as-savvy among us:
function removeLastInstance(badtext, str) {
var charpos = str.lastIndexOf(badtext);
if (charpos<0) return str;
ptone = str.substring(0,charpos);
pttwo = str.substring(charpos+(badtext.length));
return (ptone+pttwo);
}
I realize this is likely slower and more wasteful than the regex examples, but I think it might be helpful as an illustration of how string manipulations can be done. (It can also be condensed a bit, but again, I wanted each step to be clear.)
Solution 5 - Javascript
Here's a method that only uses splitting and joining. It's a little more readable so thought it was worth sharing:
String.prototype.replaceLast = function (what, replacement) {
var pcs = this.split(what);
var lastPc = pcs.pop();
return pcs.join(what) + replacement + lastPc;
};
Solution 6 - Javascript
Thought I'd answer here since this came up first in my Google search and there's no answer (outside of Matt's creative answer :)) that generically replaces the last occurrence of a string of characters when the text to replace might not be at the end of the string.
if (!String.prototype.replaceLast) {
String.prototype.replaceLast = function(find, replace) {
var index = this.lastIndexOf(find);
if (index >= 0) {
return this.substring(0, index) + replace + this.substring(index + find.length);
}
return this.toString();
};
}
var str = 'one two, one three, one four, one';
// outputs: one two, one three, one four, finish
console.log(str.replaceLast('one', 'finish'));
// outputs: one two, one three, one four; one
console.log(str.replaceLast(',', ';'));
Solution 7 - Javascript
A simple answer without any regex would be:
str = str.substr(0, str.lastIndexOf(list[i])) + 'finish'
Solution 8 - Javascript
I did not like any of the answers above and came up with the below
function isString(variable) {
return typeof (variable) === 'string';
}
function replaceLastOccurrenceInString(input, find, replaceWith) {
if (!isString(input) || !isString(find) || !isString(replaceWith)) {
// returns input on invalid arguments
return input;
}
const lastIndex = input.lastIndexOf(find);
if (lastIndex < 0) {
return input;
}
return input.substr(0, lastIndex) + replaceWith + input.substr(lastIndex + find.length);
}
Usage:
const input = 'ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty';
const find = 'teen';
const replaceWith = 'teenhundred';
const output = replaceLastOccurrenceInString(input, find, replaceWith);
console.log(output);
// output: ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteenhundred twenty
Hope that helps!
Solution 9 - Javascript
If speed is important, use this:
/**
* Replace last occurrence of a string with another string
* x - the initial string
* y - string to replace
* z - string that will replace
*/
function replaceLast(x, y, z){
var a = x.split("");
var length = y.length;
if(x.lastIndexOf(y) != -1) {
for(var i = x.lastIndexOf(y); i < x.lastIndexOf(y) + length; i++) {
if(i == x.lastIndexOf(y)) {
a[i] = z;
}
else {
delete a[i];
}
}
}
return a.join("");
}
It's faster than using RegExp.
Solution 10 - Javascript
Simple solution would be to use substring method.
Since string is ending with list element, we can use string.length and calculate end index for substring without using lastIndexOf
method
str = str.substring(0, str.length - list[i].length) + "finish"
Solution 11 - Javascript
Couldn't you just reverse the string and replace only the first occurrence of the reversed search pattern? I'm thinking . . .
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])
{
var reversedHaystack = str.split('').reverse().join('');
var reversedNeedle = list[i].split('').reverse().join('');
reversedHaystack = reversedHaystack.replace(reversedNeedle, 'hsinif');
str = reversedHaystack.split('').reverse().join('');
}
}
Solution 12 - Javascript
Old fashioned and big code but efficient as possible:
function replaceLast(origin,text){
textLenght = text.length;
originLen = origin.length
if(textLenght == 0)
return origin;
start = originLen-textLenght;
if(start < 0){
return origin;
}
if(start == 0){
return "";
}
for(i = start; i >= 0; i--){
k = 0;
while(origin[i+k] == text[k]){
k++
if(k == textLenght)
break;
}
if(k == textLenght)
break;
}
//not founded
if(k != textLenght)
return origin;
//founded and i starts on correct and i+k is the first char after
end = origin.substring(i+k,originLen);
if(i == 0)
return end;
else{
start = origin.substring(0,i)
return (start + end);
}
}
Solution 13 - Javascript
I would suggest using the replace-last npm package.
var str = 'one two, one three, one four, one';
var result = replaceLast(str, 'one', 'finish');
console.log(result);
<script src="https://unpkg.com/replace-last@latest/replaceLast.js"></script>
This works for string and regex replacements.
Solution 14 - Javascript
this way works for me. take a look at replace last character in string javascript
str.replace(/one([^one]*$)/, 'finish$1')
Solution 15 - Javascript
function replaceLast(text, searchValue, replaceValue) {
const lastOccurrenceIndex = text.lastIndexOf(searchValue)
return `${
text.slice(0, lastOccurrenceIndex)
}${
replaceValue
}${
text.slice(lastOccurrenceIndex + searchValue.length)
}`
}
Solution 16 - Javascript
str = (str + '?').replace(list[i] + '?', 'finish');