JavaScript: заменить последнее вхождение текста в строку - PullRequest
68 голосов
/ 28 апреля 2010

См. Мой фрагмент кода ниже:

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')
     }
 }

Я хочу заменить последнее вхождение слова 1 словом «конец» в строке, что у меня не будет работать, потому что метод замены будет только заменятьпервое возникновение этого.Кто-нибудь знает, как я могу изменить этот фрагмент так, чтобы он заменял только последний экземпляр 'one'

Ответы [ 13 ]

87 голосов
/ 28 апреля 2010

Ну, если строка действительно заканчивается шаблоном, вы можете сделать это:

str = str.replace(new RegExp(list[i] + '$'), 'finish');
34 голосов
/ 28 апреля 2010

Вы можете использовать String#lastIndexOf, чтобы найти последнее вхождение слова, а затем String#substring и объединение, чтобы построить строку замены.

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

... или в том же духе.

17 голосов
/ 28 апреля 2010

Я знаю, что это глупо, но сегодня утром я чувствую себя креативно:

'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');
11 голосов
/ 27 мая 2011

Не так элегантно, как регулярное выражение отвечает выше, но легче следовать за не слишком подкованным среди нас:

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);
}

Я понимаю, что это, вероятно, медленнее и расточительнее, чем примеры регулярных выражений, но я думаю, что это может быть полезно в качестве иллюстрации того, как можно выполнять манипуляции со строками. (Это также может быть немного сжато, но опять же, я хотел, чтобы каждый шаг был понятен.)

8 голосов
/ 10 августа 2013

Думаю, что я отвечу здесь, так как это появилось первым в моем поиске в Google, и нет ответа (кроме творческого ответа Мэтта :)), который обычно заменяет последнее вхождение строки символов, когда текст для замены может быть в конце строки.

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(',', ';'));
5 голосов
/ 06 января 2016

Вот метод, который использует только расщепление и соединение. Это немного более читабельно, поэтому подумал, что стоит поделиться:

    String.prototype.replaceLast = function (what, replacement) {
        var pcs = this.split(what);
        var lastPc = pcs.pop();
        return pcs.join(what) + replacement + lastPc;
    };
3 голосов
/ 16 августа 2018

Простой ответ без каких-либо регулярных выражений будет:

str = str.substr(0, str.lastIndexOf(list[i])) + 'finish'
2 голосов
/ 17 сентября 2014

Не могли бы вы просто перевернуть строку и заменить только первое вхождение измененного шаблона поиска? Я думаю . , .

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('');
     }
 }
1 голос
/ 12 ноября 2018

Простым решением было бы использование метода подстроки. Поскольку строка заканчивается элементом списка, мы можем использовать string.length и рассчитать индекс конца для подстроки без использования lastIndexOf method

str = str.substring(0, str.length - list[i].length) + "finish"

1 голос
/ 23 февраля 2017

Если важна скорость, используйте это:

/**
 * 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...