814 Stimmen

Schnellste Methode zum Ersetzen aller Instanzen eines Zeichens in einer Zeichenkette

Was ist der schnellste Weg, um alle Instanzen einer Zeichenfolge/Zeichen in einer Zeichenfolge in JavaScript zu ersetzen? A while , a for -Schleife, einen regulären Ausdruck?

4 Stimmen

Eine while- und eine for-Schleife würden beide mit einem einfachen Algorithmus in O(n) laufen. Nicht wirklich sicher, was ist die Zeitkomplexität für Javascript Regex-Engine in diesem Fall, aber meine Vermutung ist seine optimiert genug, um in O(n) für eine einfache String-Match laufen.

3 Stimmen

Dies scheint wie Mikro-Optimierung zu mir - hat Performance-Profiling zeigen die Zeichenfolge-Ersetzung zu den langsamsten Teil Ihres Programms sein?

0 Stimmen

Nein, ich habe mein Skript nicht einem Leistungsprofil unterzogen, ich wollte nur sicherstellen, dass ich die schnellste verfügbare Funktion verwende.

15voto

Neel Kamal Punkte 201

Verwenden Sie das Regex-Objekt wie folgt

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

Sie ersetzt alle Vorkommen von " in ' .

13voto

DamienS Punkte 141

Ich denke, dass das Beispiel mit der Groß- und Kleinschreibung im obigen Link die bei weitem schnellste Lösung wäre.

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 würde lauten "Dies ist ein Test des Notrufsystems."

13voto

Rick Velde Punkte 551

Ich denke, die richtige Antwort ist, dass es ganz darauf ankommt, wie Ihre Eingaben aussehen. Ich habe eine JsFiddle um eine Reihe von ihnen und einige meiner eigenen gegen verschiedene Eingaben auszuprobieren. Egal wie ich die Ergebnisse betrachte, ich sehe keinen klaren Gewinner.

  • RegExp war in keinem der Testfälle der schnellste, aber auch nicht der schlechteste.
  • Der Split/Join-Ansatz scheint bei spärlichen Ersetzungen am schnellsten zu sein.
  • Dieses von mir geschriebene Programm scheint am schnellsten für kleine Eingaben und dichte Ersetzungen:

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

9voto

Zibri Punkte 7918

Ich habe gerade einen Benchmark programmiert und die ersten 3 Antworten getestet. Es scheint, dass für kurze Zeichenfolgen (<500 Zeichen)
die drittmeisten Stimmen sind schneller als die zweitmeisten Stimmen.

Bei langen Zeichenfolgen (fügen Sie ".repeat(300)" zur Testzeichenfolge hinzu) ist die schnellere Antwort 1, gefolgt von der zweiten und der dritten.

Anmerkung:

Die obigen Angaben gelten für Browser mit v8-Engine (Chrome/Chromium usw.).
Mit Firefox (SpiderMonkey-Engine) sind die Ergebnisse völlig anders
Überzeugen Sie sich selbst!! Firefox mit der dritten Lösung scheint zu sein
mehr als 4,5 mal schneller als Chrome mit der ersten Lösung... verrückt :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>

Der Test läuft 10 Sekunden (+2 Sekunden) lang, während Sie auf die Schaltfläche klicken.

Meine Ergebnisse (auf demselben 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)

Schöner Schlamassel, was?

Ich habe mir die Freiheit genommen, weitere Testergebnisse hinzuzufügen

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)

Chrome auf dem Galaxy Note 4

1. replace4 score: 100% *winner* (99.82)
2. replace1 score: 91.04% speed of winner. (90.88)
3. replace3 score: 70.27% speed of winner. (70.15)
4. replace2 score: 38.25% speed of winner. (38.18)

6voto

Crozin Punkte 42878

Was am schnellsten ist, weiß ich nicht, aber ich weiß, was am lesbarsten ist - das, was am kürzesten und einfachsten ist. Auch wenn es ein bisschen langsamer ist als andere Lösungen, lohnt es sich, es zu benutzen.

Also benutzen:

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

Und genießen Sie guten Code anstelle von schnellerem (naja... 1/100000 Sek. ist kein Unterschied) und hässlichem Code. ;)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X