Ответ 1
Ну, если строка действительно заканчивается шаблоном, вы можете сделать это:
str = str.replace(new RegExp(list[i] + '$'), 'finish');
Смотрите мой фрагмент кода ниже:
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')
}
}
Я хочу заменить последнее вхождение слова one со словом finish в строке, то, что у меня не будет работать, потому что метод replace заменит только первое его появление. Кто-нибудь знает, как я могу изменить этот фрагмент, чтобы он заменял только последний экземпляр "одного"
Ну, если строка действительно заканчивается шаблоном, вы можете сделать это:
str = str.replace(new RegExp(list[i] + '$'), 'finish');
Вы можете использовать String#lastIndexOf
, чтобы найти последнее вхождение слова, а затем String#substring
и конкатенацию, чтобы построить заменяющую строку.
n = str.lastIndexOf(list[i]);
if (n >= 0 && n + list[i].length >= str.length) {
str = str.substring(0, n) + "finish";
}
... или вдоль этих строк.
Я знаю, что это глупо, но сегодня я чувствую себя творчески:
'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"
Итак, все, что вам нужно сделать, это добавить эту функцию в прототип String:
String.prototype.replaceLast = function (what, replacement) {
return this.split(' ').reverse().join(' ').replace(new RegExp(what), replacement).split(' ').reverse().join(' ');
};
Затем запустите его так:
str = str.replaceLast('one', 'finish');
Одно ограничение, которое вы должны знать, состоит в том, что, поскольку функция разделяется пробелом, вы, вероятно, не можете найти/заменить что-либо пробелом.
Собственно, теперь, когда я думаю об этом, вы можете обойти проблему "пространства", разделив его на пустой токен.
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');
Не так изящно, как регулярное выражение отвечает выше, но легче следовать за не-подкованным среди нас:
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);
}
Я понимаю, что это, скорее всего, медленнее и более расточительно, чем примеры регулярных выражений, но я думаю, что это может быть полезно в качестве иллюстрации того, как могут выполняться строковые манипуляции. (Его также можно немного сжать, но опять же, я хотел, чтобы каждый шаг был ясным.)
Думаю, что я бы ответил здесь, так как это появилось первым в моем поиске Google, и нет ответа (вне ответа Matt creat:):), который в общем случае заменяет последнее вхождение строки символов, когда текст для замены может не быть в конце строки.
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(',', ';'));
Здесь используется метод, который использует только разделение и объединение. Это немного более читаемо, поэтому подумал, что стоит поделиться:
String.prototype.replaceLast = function (what, replacement) {
var pcs = this.split(what);
var lastPc = pcs.pop();
return pcs.join(what) + replacement + lastPc;
};
Простой ответ без каких-либо регулярных выражений будет:
str = str.substr(0, str.lastIndexOf(list[i])) + 'finish'
Не могли бы вы просто изменить строку и заменить только первое появление обратного шаблона поиска? Я думаю.,.
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('');
}
}
Старомодный и большой код, но максимально эффективный:
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);
}
}
Если скорость важна, используйте это:
/**
* 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("");
}
Это быстрее, чем использование RegExp.
Простым решением было бы использовать метод подстроки. Так как строка заканчивается элементом списка, мы можем использовать string.length и вычислить индекс конца для подстроки без использования метода lastIndexOf
str = str.substring(0, str.length - list[i].length) + "finish"
Я бы предложил использовать пакет replace-last npm.
var str = 'one two, one three, one four, one';
var result = replaceLast(str, 'one', 'finish');
console.log(result);
<script src="https://unpkg.com/[email protected]/replaceLast.js"></script>
Мне не понравился ни один из приведенных выше ответов, и я пришел к следующему
function replaceLastOccurrenceInString(input, find, replaceWith) {
if (!input || !find || !replaceWith || !input.length || !find.length || !replaceWith.length) {
// 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);
}
Использование:
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
Надеюсь, это поможет!
str = (str + '?').replace(list[i] + '?', 'finish');