关于javascript:替换字符串中所有字符实例的最快方法

Fastest method to replace all instances of a character in a string

在javascript中,替换字符串中字符串/字符的所有实例的最快方法是什么?一个while,一个for循环,一个正则表达式?


最简单的方法是使用带有g标志的正则表达式替换所有实例:

1
str.replace(/foo/g,"bar")

这将用字符串str中的bar替换所有出现的foo。如果只有一个字符串,则可以将其转换为如下regexp对象:

1
2
var pattern ="foobar",
    re = new RegExp(pattern,"g");


尝试此替换所有:http://dumpsite.com/forum/index.php?主题=4.msg8 msg8

1
2
3
4
String.prototype.replaceAll = function(str1, str2, ignore)
{
    return this.replace(new RegExp(str1.replace(/([\/\,\!\\\^\$\{\}\[\]\(\)\.\*\+\?\|\<\>\-\&])/g,"\\$&"),(ignore?"gi":"g")),(typeof(str2)=="string")?str2.replace(/\$/g,"$$$$"):str2);
}

它很快,在所有这些条件下都能工作很多其他人都失败了:

1
2
3
4
5
6
7
8
9
10
11
"x".replaceAll("x","xyz");
// xyz

"x".replaceAll("","xyz");
// xyzxxyz

"aA".replaceAll("a","b", true);
// bb

"Hello???".replaceAll("?","!");
// Hello!!!

让我知道你是否能打破它,或者你有更好的东西,但要确保它能通过这4个测试。


1
2
var mystring = 'This is a string';
var newString = mystring.replace(/i/g,"a");

现在的新闻字符串是"thas as a strang"


您也可以尝试:

1
string.split('foo').join('bar');


仅仅从速度问题来考虑,我相信上面链接中提供的区分大小写的示例是迄今为止最快的解决方案。

1
2
3
4
5
6
7
8
9
10
var token ="

"
;
var newToken ="";
var oldStr ="This is a test

of the emergency broadcasting

system."
;
newStr = oldStr.split(token).join(newToken);

Newstr应该是"这是对紧急广播系统的测试。"


您可以使用以下内容:

1
newStr = str.replace(/[^a-z0-9]/gi, '_');

1
newStr = str.replace(/[^a-zA-Z0-9]/g, '_');

这将替换所有不是字母或数字的字符。简单地更改要替换的下划线值。


我认为真正的答案是它完全取决于你输入的内容是什么样子的。我创建了一个JSfiddle来尝试其中的一组,并针对各种输入创建了一些自己的JSfiddle。无论我如何看待结果,我都看不到明确的赢家。

  • 在任何测试用例中,regexp都不是最快的,但也不错。
  • 对于稀疏替换,拆分/联接方法似乎最快。
  • 我写的这个对于小输入和密集的替换:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    function replaceAllOneCharAtATime(inSource, inToReplace, inReplaceWith) {
        var output="";
        var firstReplaceCompareCharacter = inToReplace.charAt(0);
        var sourceLength = inSource.length;
        var replaceLengthMinusOne = inToReplace.length - 1;
        for(var i = 0; i < sourceLength; i++){
            var currentCharacter = inSource.charAt(i);
            var compareIndex = i;
            var replaceIndex = 0;
            var sourceCompareCharacter = currentCharacter;
            var replaceCompareCharacter = firstReplaceCompareCharacter;
            while(true){
                if(sourceCompareCharacter != replaceCompareCharacter){
                output += currentCharacter;
                break;
            }
            if(replaceIndex >= replaceLengthMinusOne) {
                i+=replaceLengthMinusOne;
                output += inReplaceWith;
                //was a match
                break;
            }
            compareIndex++; replaceIndex++;
            if(i >= sourceLength){
                // not a match
                break;
            }
            sourceCompareCharacter = inSource.charAt(compareIndex)
                replaceCompareCharacter = inToReplace.charAt(replaceIndex);
            }  
            replaceCompareCharacter += currentCharacter;
        }
        return output;
    }


像这样使用regex对象

埃多克斯1〔6〕

它将把所有出现的"替换成'


使用String对象的replace()方法。

如所选答案中所述,应在regex中使用/g标志,以便替换字符串中子字符串的所有实例。


我在意识到我在10年前写的一个实现可能并没有完全工作之后,尝试了很多这些建议(在一个早已被遗忘的系统中,令人讨厌的生产错误,不是一直都是这样吗?!)我注意到的是,我试过的那些(我没有全部试过)和我的有同样的问题,也就是说,它们不会替换每一个事件,只会替换第一个事件,至少对于我的测试用例来说,"test….txt"到"test.txt",用"."替换".."。也许我错过了雷杰克斯的情况?但我离题了…

因此,我重写了我的实现,如下所示。这很简单,虽然我怀疑不是最快的,但我也不认为这与现代的JS引擎有什么区别,除非你在一个很紧的循环中这样做,当然,但这总是适用于任何事情…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function replaceSubstring(inSource, inToReplace, inReplaceWith) {

  var outString = inSource;
  while (true) {
    var idx = outString.indexOf(inToReplace);
    if (idx == -1) {
      break;
    }
    outString = outString.substring(0, idx) + inReplaceWith +
      outString.substring(idx + inToReplace.length);
  }
  return outString;

}

希望能帮助别人!


我不知道什么是最快的,但我知道什么是最可读的——最短最简单的。即使比其他解决方案慢一点,也值得使用。

所以使用:

1
2
"string".replace("a","b");
"string".replace(/abc?/g,"def");

享受好的代码而不是更快(好吧…1/100000秒和丑的没什么区别。;)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Find, Replace, Case
// i.e"Test to see if this works? (Yes|No)".replaceAll('(Yes|No)', 'Yes!');
// i.e.2"Test to see if this works? (Yes|No)".replaceAll('(yes|no)', 'Yes!', true);
String.prototype.replaceAll = function(_f, _r, _c){

  var o = this.toString();
  var r = '';
  var s = o;
  var b = 0;
  var e = -1;
  if(_c){ _f = _f.toLowerCase(); s = o.toLowerCase(); }

  while((e=s.indexOf(_f)) > -1)
  {
    r += o.substring(b, b+e) + _r;
    s = s.substring(e+_f.length, s.length);
    b += e+_f.length;
  }

  // Add Leftover
  if(s.length>0){ r+=o.substring(o.length-s.length, o.length); }

  // Return New String
  return r;
};


@gumbo添加额外答案-user.email.replace(/foo/gi,"bar");

1
2
3
/foo/g - Refers to the all string to replace matching the case sensitive

/foo/gi - Refers to the without case sensitive and replace all For Eg: (Foo, foo, FoO, fOO)

演示