web-dev-qa-db-de.com

Schnellste Methode zum Ersetzen aller Instanzen eines Zeichens in einer Zeichenfolge

Was ist der schnellste Weg, um alle Instanzen einer Zeichenfolge/eines Zeichens in einer Zeichenfolge in JavaScript zu ersetzen? Eine while, eine for-Schleife, ein regulärer Ausdruck?

534

Am einfachsten wäre es, einen regulären Ausdruck mit dem Flag g zu verwenden, um alle Instanzen zu ersetzen:

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

Dadurch werden alle Vorkommen von foo durch bar in der Zeichenfolge str ersetzt. Wenn Sie nur eine Zeichenfolge haben, können Sie diese wie folgt in ein RegExp-Objekt konvertieren:

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

Versuchen Sie Folgendes: Alle ersetzen: 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);
} 

Es ist sehr schnell, und es wird für ALLE diese Bedingungen funktionieren.

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

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

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

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

Lass es mich wissen, wenn du es kaputt machen kannst oder etwas Besseres hast, aber stelle sicher, dass es diese 4 Tests bestehen kann.

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

newString heißt jetzt "Thas wie ein Strang"

80

Sie können auch versuchen:

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

Wenn ich nur aus Geschwindigkeitsgründen darüber nachdenke, glaube ich, dass das unter Link oben angegebene Fallbeispiel 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äre "Dies ist ein Test des Notrufsystems."

9
ADamienS

Sie können Folgendes verwenden:

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

oder

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

Dies wird alle Zeichen ersetzen, bei denen es sich nicht um Buchstaben oder Zahlen handelt ('_'). Ändern Sie einfach den Unterstrichwert für das, was Sie ersetzen möchten. 

9
ssamuel68

Ich denke, die wirkliche Antwort ist, dass es völlig davon abhängt, wie Ihre Eingaben aussehen. Ich habe ein JsFiddle erstellt, um ein paar davon und ein paar eigene gegen verschiedene Eingaben zu testen. Egal wie ich die Ergebnisse betrachte, ich sehe keinen klaren Gewinner.

  • RegExp war in keinem der Testfälle der Schnellste, aber auch nicht schlecht. 
  • Der Split/Join-Ansatz scheint bei spärlichen Ersetzungen am schnellsten zu sein.
  • Dieser, den ich geschrieben habe, scheint bei kleinen Eingaben und dichtem Ersatz am schnellsten zu sein:

    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

Verwenden Sie ein Regex-Objekt wie dieses

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

Es ersetzt alle Vorkommen von " in '

6
Neel Kamal

Verwenden Sie die replace() -Methode des String-Objekts.

Wie in der ausgewählten Antwort erwähnt, sollte das Flag/g im regulären Ausdruck verwendet werden, um alle -Instanzen des Teilstrings im String zu ersetzen.

6
Franci Penov

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

Verwenden Sie also:

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

Und genieße guten Code statt schneller (gut ... 1/100000 Sek. Ist kein Unterschied) und hässlicher. ;)

6
Crozin

Ich habe einige dieser Vorschläge ausprobiert, nachdem ich gemerkt hatte, dass eine Implementierung, die ich vor fast 10 Jahren geschrieben hatte, tatsächlich nicht vollständig funktionierte (böser Produktionsfehler in einem längst vergessenen System, ist das nicht immer der Fall ?!) ... was mir aufgefallen ist, dass die, die ich ausprobierte (ich habe sie nicht alle ausprobiert), das gleiche Problem hatten wie das meine, das heißt, sie würden nicht JEDES Vorkommen ersetzen, nur das erste, zumindest für meinen Testfall "test .... txt" runter zu "test.txt" bekommen, indem ".." durch "." ersetzt wird ... vielleicht habe ich die Regex-Situation so verpasst? Aber ich schweife ab...

Also habe ich meine Implementierung wie folgt umgeschrieben. Es ist ziemlich einfach, obwohl ich vermute, nicht der Schnellste zu sein, aber ich glaube auch nicht, dass der Unterschied bei modernen JS-Motoren von Bedeutung sein wird, es sei denn, Sie machen das natürlich in einer engen Schleife, aber das ist immer der Fall.

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;

}

Hoffe das hilft jemandem!

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

Ich habe gerade einen Benchmark programmiert und die ersten 3 Antworten getestet. Es scheint, dass für kurze Zeichenfolgen (<500 Zeichen)
Die am dritthäufigsten gewählte Antwort ist schneller als die am zweithäufigsten gewählte.

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

Anmerkung:

Dies gilt für Browser, die die v8-Engine (Chrom/Chrom usw.) verwenden.
Mit Firefox (SpiderMonkey-Engine) sind die Ergebnisse völlig anders
Prüft 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 dauert 10 Sekunden (+ 2 Sekunden), wenn 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)

Nettes Durcheinander, was?

Hat sich erlaubt, 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)
0
Zibri

@Gumbo zusätzliche Antwort hinzufügen - 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