2010-04-28 3 views
47

Смотрите мой фрагмент кода ниже:JavaScript: заменить последнее вхождение текста в строке

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

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

ответ

67

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

str = str.replace(new RegExp(list[i] + '$'), 'finish'); 
+1

Хорошая идея. Необходимо сначала избежать этой строки (хотя и не с предоставленными ею образцами данных), что нетривиально. :-( –

+0

Большое спасибо – Ruth

+0

@Ruth no prob! @TJ да, действительно, это правда: Рут, если вы закончите словами «слова», которые вы ищете, включая специальные символы, используемые для регулярных выражений, вам понадобится чтобы «убежать» от тех, что, как говорит TJ, немного сложнее (не невозможно, хотя). – Pointy

30

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

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

... или по этим линиям.

+0

Большое спасибо – Ruth

+1

Другой пример: \t \t \t \t var nameSplit = item.name.lastIndexOf (","); \t \t \t \t, если (nameSplit = -1!) \t \t \t \t \t item.name = item.name.substr (0, nameSplit) + "и" + item.name.substr (nameSplit + 2); –

16

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

'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.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'); 
+0

Большое спасибо – Ruth

+1

Вы называете это глупым, мы называем это полезным! – Alexander

+7

@ Александр Ухх, пожалуйста, не используйте это в производственном коде ... Или любой код ... Достаточно простого регулярного выражения. – Slight

9

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

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

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

5

Думал, что я бы ответил здесь, так как это было первым в моем поиске 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(',', ';')); 
1

Старомодные и большой код, но эффективно, как это возможно:

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

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

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
str = (str + '?').replace(list[i] + '?', 'finish'); 
+6

Обычно, как правило, требуется объяснение в дополнение к ответу – 2015-02-12 23:44:00

3

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

String.prototype.replaceLast = function (what, replacement) { 
     var pcs = this.split(what); 
     var lastPc = pcs.pop(); 
     return pcs.join(what) + replacement + lastPc; 
    }; 
1

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

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

Смежные вопросы