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?
- Ersetzen aller Vorkommen einer Zeichenkette in JavaScript (79 Antworten )
Antworten
Zu viele Anzeigen?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."
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; }
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)
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. ;)
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.
5 Stimmen
Ich habe einen JSPerf gemacht, der globale Regex und eine for-Schleife vergleicht: jsperf.com/javascript-ersetzen-alle . Wenn ich die Tests richtig geschrieben habe, sieht es so aus, als ob die Antwort "es kommt darauf an" lautet.
0 Stimmen
Nach diesem jsperf.com/split-join-vs-replace/16 die schnellste Methode ist die Verwendung von
split join
1 Stimmen
Mögliches Duplikat von Ersetzen aller Vorkommen einer Zeichenkette in JavaScript
0 Stimmen
Ich bin nicht sicher, wann
replace
wurde optimiert, abersplit
-join
ist jetzt etwa 40+% langsamer.0 Stimmen
Ich verstehe nicht, warum in Chrome 97,
replaceAll
(nativ) sollte langsamer sein alssplit().join()
im Umgang mit großen Strings? jsben.ch/AxKZ3 (In Firefox sieht es gut aus)