2010-04-28 141 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

好主意。首先需要转义该字符串(尽管不是与她的示例数据一致),这是非平凡的。 :-( – 2010-04-28 13:13:02

+0

非常感谢你 – Ruth 2010-04-28 13:26:01

+0

@Ruth no prob!@TJ是的,事实的确如此:Ruth如果最终得到的是包含用于正则表达式的特殊字符的“词”,则需要TJ说这是一个有点棘手的问题(虽然不是不可能) – Pointy 2010-04-28 21:56:41

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 2010-04-28 13:25:24

+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); – 2012-02-13 17:52:38

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 2010-04-28 13:26:59

+1

您称之为无聊,我们称它为有帮助! – Alexander 2014-09-12 13:22:13

+7

@Alexander Uhhh,请不要在生产代码中使用它...或者任何代码...一个简单的正则表达式就足够了。 – Slight 2016-06-20 16:46:47

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搜索中首先出现,并且没有答案(除了Matt的创造性答案:)),通常取代最后一次出现的字符串,当要替换的文本可能不在字符串末尾时。

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

下面是仅使用分裂和加入的方法。这是一个有点更具可读性,从而认为这是值得分享:

​​
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(""); 
} 

这比使用正则表达式更快。

相关问题