web-dev-qa-db-ja.com

文字列内の文字のすべてのインスタンスを置き換える最も速い方法

JavaScriptで文字列内の文字列/文字のすべてのインスタンスを置き換えるための最速の方法は何ですか? whilename__、forname __-ループ、正規表現

552

最も簡単な方法は、すべてのインスタンスを置き換えるためにgフラグを持つ正規表現を使用することです。

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

これにより、文字列foo内のすべてのbarstrに置き換えられます。あなたが文字列を持っているだけなら、あなたはこのようにRegExpオブジェクトにそれを変換することができます:

var pattern = "foobar",
    re = new RegExp(pattern, "g");
969
Gumbo

このreplaceAllを試してみてください: http://dumpsite.com/forum/index.php?topic=4.msg8#msg8

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

それは非常に速く、そして他の多くのものが失敗するこれらのすべての条件に対してうまくいくでしょう。

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

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

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

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

あなたがそれを破ることができるかどうかを教えてください、またはあなたがより良いものを持っているが、それはこれらの4つのテストに合格できることを確認してください。

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

newStringは「Thas as strang」になりました

80

また、試すことができます:

string.split('foo').join('bar');
33
Vlada

速度の問題から考えるだけで、上記のリンクで提供されている大文字と小文字を区別する例が、はるかに速い解決策になると思います。

var token = "\r\n";
var newToken = " ";
var oldStr = "This is a test\r\nof the emergency broadcasting\r\nsystem.";
newStr = oldStr.split(token).join(newToken);

newStrは「これは緊急放送システムのテストです」となります。

10
ADamienS

次のものを使用できます。

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

または

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

これは、文字または数字ではないすべての文字を( '_')に置き換えます。あなたがそれを置き換えたいものは何でものために単純にアンダースコア値を変更してください。

10
ssamuel68

本当の答えは、それがあなたの意見がどのように見えるかに完全に依存しているということだと思います。私は JsFiddle を作成して、さまざまな入力に対してこれらの束と自分のカップルを試してみました。どのように結果を見ても、明確な勝者はわかりません。

  • RegExpはどのテストケースでも最速ではありませんでしたが、それほど悪くもありませんでした。
  • 分割/結合のアプローチは、スパースな置き換えのために最速のようです。
  • これが私が書いたものは、小さい入力と密な置き換えのために最も速いようです:

    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;
    }
    
8
Rick Velde

このような正規表現オブジェクトを使う

var regex = new RegExp('"', 'g'); str = str.replace(regex, '\'');

これはすべての"'に置き換えます。

7
Neel Kamal

Stringオブジェクトの replace() メソッドを使用してください。

選択した回答で述べたように、文字列内の部分文字列の all インスタンスを置き換えるには、正規表現で/ gフラグを使用します。

6
Franci Penov

一番速いのはわかりませんが、最も読みやすいものはわかっています - つまり、最も短く最も簡単なものです。たとえそれが他の解決策より少し遅いとしてもそれは使う価値があります。

だから使用:

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

そして、より速い(よく・・・ 1/100000秒は違いではありません)そして醜いコードの代わりに良いコードを楽しんでください。 ;)

6
Crozin

私がこれを書いた実装がおそらく10年近く前には実際には完全には機能しないことを認識した後、これらの提案をいくつか試しました(長い間忘れられていたシステムの厄介なプロダクションバグ、いつもそうではありませんか?)。 ...私が気付いたのは、私が試したもの(私は全部試したわけではない)は私のものと同じ問題を抱えていたということです。 ".."を "。"に置き換えることで、 "test .... txt"から "test.txt"に変更されます。しかし私は脱線します...

そこで、私は次のように私の実装を書き直しました。私は最速ではないと思うけれども、それがかなり単純で単純だが、違いが現代のJSエンジンでは問題にならないとも思うが、もちろんこれをタイトなループの中でやっていない限り。

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;

}

誰かに役立つことを願っています!

5
// 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;
};
2
MadHatter

ベンチマークをコーディングして、最初の3つの答えをテストしました。短い文字列(<500文字)のようです
3番目に多く投票された回答は、2番目に多く投票された回答よりも高速です。

長い文字列(テスト文字列に ".repeat(300)"を追加)の場合、回答1の後に2番目と3番目が続きます。

注:

上記は、v8エンジン(クロム/クロムなど)を使用するブラウザに当てはまります。
firefox(SpiderMonkeyエンジン)では、結果はまったく異なります
自分で確認してください!! 3番目のソリューションを備えたFirefoxは
最初の解決策では、Chromeより4.5倍以上高速です...クレイジー:D

function log(data) {
  document.getElementById("log").textContent += data + "\n";
}

benchmark = (() => {

  time_function = function(ms, f, num) {
    var z;
    var t = new Date().getTime();
    for (z = 0;
      ((new Date().getTime() - t) < ms); z++) f(num);
    return (z / ms)
  } // returns how many times the function was run in "ms" milliseconds.


  function benchmark() {
    function compare(a, b) {
      if (a[1] > b[1]) {
        return -1;
      }
      if (a[1] < b[1]) {
        return 1;
      }
      return 0;
    }

    // functions

    function replace1(s) {
      s.replace(/foo/g, "bar")
    }

String.prototype.replaceAll2 = function(_f, _r){ 

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

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

    function replace2(s) {
      s.replaceAll("foo", "bar")
    }

    function replace3(s) {
      s.split('foo').join('bar');
    }

    function replace4(s) {
      s.replaceAll2("foo", "bar")
    }


    funcs = [
      [replace1, 0],
      [replace2, 0],
      [replace3, 0],
      [replace4, 0]
    ];

    funcs.forEach((ff) => {
      console.log("Benchmarking: " + ff[0].name);
      ff[1] = time_function(2500, ff[0], "foOfoobarBaR barbarfoobarf00".repeat(10));
      console.log("Score: " + ff[1]);

    })
    return funcs.sort(compare);
  }

  return benchmark;
})()
log("Starting benchmark...\n");
res = benchmark();
console.log("Winner: " + res[0][0].name + " !!!");
count = 1;
res.forEach((r) => {
  log((count++) + ". " + r[0].name + " score: " + Math.floor(10000 * r[1] / res[0][1]) / 100 + ((count == 2) ? "% *winner*" : "% speed of winner.") + " (" + Math.round(r[1] * 100) / 100 + ")");
});
log("\nWinner code:\n");
log(res[0][0].toString());
<textarea rows="50" cols="80" style="font-size: 16; resize:none; border: none;" id="log"></textarea>

ボタンをクリックすると、テストは10秒(+2秒)実行されます。

私の結果(同じPC上):

Chrome/Linux Ubuntu 64:
1. replace1 score: 100% *winner* (766.18)
2. replace4 score: 99.07% speed of winner. (759.11)
3. replace3 score: 68.36% speed of winner. (523.83)
4. replace2 score: 59.35% speed of winner. (454.78)

Firefox/Linux Ubuntu 64
1. replace3 score: 100% *winner* (3480.1)
2. replace1 score: 13.06% speed of winner. (454.83)
3. replace4 score: 9.4% speed of winner. (327.42)
4. replace2 score: 4.81% speed of winner. (167.46)

すてきな混乱?

さらにテスト結果を追加する自由を探します

Chrome/Windows 10
1. replace1 score: 100% *winner* (742.49)
2. replace4 score: 85.58% speed of winner. (635.44)
3. replace2 score: 54.42% speed of winner. (404.08)
4. replace3 score: 50.06% speed of winner. (371.73)

Firefox/Windows 10
1. replace3 score: 100% *winner* (2645.18)
2. replace1 score: 30.77% speed of winner. (814.18)
3. replace4 score: 22.3% speed of winner. (589.97)
4. replace2 score: 12.51% speed of winner. (331.13)

Edge/Windows 10
1. replace1 score: 100% *winner* (1251.24)
2. replace2 score: 46.63% speed of winner. (583.47)
3. replace3 score: 44.42% speed of winner. (555.92)
4. replace4 score: 20% speed of winner. (250.28)
0
Zibri

@Gumboが追加の回答を追加します - user.email.replace(/ foo/gi、 "bar");

/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)

_ demo _

0
Surya R Praveen