Der schnellste Weg, um zu überprüfen, ob eine Zeichenfolge eine andere Teilzeichenfolge in JavaScript enthält?

162

Ich arbeite mit einem Leistungsproblem in JavaScript. Ich möchte nur fragen: Wie kann ich am schnellsten überprüfen, ob eine Zeichenfolge eine andere Teilzeichenfolge enthält (ich benötige nur den booleschen Wert)? Könnten Sie bitte Ihre Idee und einen Beispiel-Snippet-Code vorschlagen?

Đinh Hồng Châu
quelle
Fragen Sie nach einem festen Teilstring oder benötigen Sie einen regulären Ausdruck (ich bin etwas verwirrt über die Verwendung des regexTags)?
Tim Pietzcker
1
Dieser Beitrag wäre hilfreich .. stackoverflow.com/questions/1789945/javascript-string-contains
mtk
Wie wäre es, wenn Sie den String in ein Array um Leerzeichen aufteilen und eine Array-Schnittmenge erstellen? stackoverflow.com/questions/1885557/…
giorgio79
jsben.ch/#/aWxtF
EscapeNetscape

Antworten:

314

Sie haben zwei Möglichkeiten:

  1. Regulärer Ausdruck :

    (new RegExp('word')).test(str)
    // or
    /word/.test(str)
  2. indexOf::

    str.indexOf('word') !== -1

Reguläre Ausdrücke scheinen schneller zu sein (zumindest in Chrome 10).

Leistungstest - kurzer Heuhaufen
Leistungstest - langer Heuhaufen


Update 2011:

Es kann nicht mit Sicherheit gesagt werden, welche Methode schneller ist. Die Unterschiede zwischen den Browsern sind enorm. Während in Chrome 10 indexOfschneller zu sein scheint, indexOfist Safari 5 deutlich langsamer als jede andere Methode.

Du musst es selbst sehen und versuchen. Es hängt von Ihren Bedürfnissen ab. Zum Beispiel ist eine Suche ohne Berücksichtigung der Groß- und Kleinschreibung mit regulären Ausdrücken viel schneller.


Update 2018:

Um zu verhindern, dass Benutzer die Tests selbst ausführen, sind hier die aktuellen Ergebnisse für die meisten gängigen Browser aufgeführt. Die Prozentsätze geben eine Leistungssteigerung gegenüber dem nächstschnellsten Ergebnis an (das zwischen den Browsern variiert):

Chrome: indexOf (~ 98% schneller) <-- wow
Firefox: zwischengespeichertes RegExp (~ 18% schneller)
IE11: zwischengespeichertes RegExp (~ 10% schneller)
Edge: indexOf (~ 18% schneller)
Safari: zwischengespeichertes RegExp (~ 0,4% schneller)

Beachten Sie, dass zwischengespeichertes RegExp : var r = new RegExp('simple'); var c = r.test(str);im Gegensatz zu:/simple/.test(str)

Felix Kling
quelle
3
Dies kann nur dann etwas schneller sein, wenn der zu suchende Text vorher bekannt ist (dh nicht in einer Variablen gespeichert ist), da der reguläre Ausdruck während der Analysezeit von der JavaScript-Engine erstellt wird. Wenn Sie nach einer Zeichenfolge suchen möchten, die in einer Variablen in einer anderen Zeichenfolgenvariablen enthalten ist, ist indexOf die schnellste, da Sie ein RegExp-Objekt erstellen und die Zeichenfolge verarbeiten müssen, um Sonderzeichen usw. zu umgehen.
Stephen Chung
Erfahrungsgemäß kann indexOf für die Suche ohne Berücksichtigung der Groß- und Kleinschreibung schneller sein, wenn Sie .toLowerCase für alles verwenden, was Sie zuerst suchen
Hayk Saakian
Ich schreibe eine Office 2013-App mit der Office-Javascript-API von Microsoft und die Verwendung indexOffunktioniert nicht. Ich bin mir nicht sicher warum. Die Verwendung von Regex ist jedoch möglich. Dies ist ein Randfall, aber andere könnten auf dasselbe Problem stoßen.
Andy Mercer
Gibt es einen Grund, warum substr () keine der möglichen Lösungen ist? Ich denke, es ist in vielen Situationen viel schneller als die RegEx-Lösung. Ich weiß jedoch nicht, wie es mit indexOf () verglichen wird (wenn Sie es also weggelassen haben, weil es immer schlechter abschneidet als indexOf (), ist das in Ordnung, fügen Sie möglicherweise einen Hinweis zu diesem Effekt hinzu.) BEARBEITEN : Dieser JSperf-Link zeigt einige interessante Ergebnisse. Kurzversion: indexOf () ist die schnellste aller Methoden. Dies kann jedoch je nach Zeichenfolgenlänge und sich wiederholenden Mustern variieren.
Byson
1
@Bison: Sie können substr nur verwenden, wenn Sie bereits wissen, wo Sie suchen müssen. Ich habe mich nur auf generische Lösungen konzentriert.
Felix Kling
17

Geht das für dich?

string1.indexOf(string2) >= 0

Bearbeiten: Dies ist möglicherweise nicht schneller als ein RegExp, wenn der String2 wiederholte Muster enthält. In einigen Browsern ist indexOf möglicherweise viel langsamer als RegExp. Zeige Kommentare.

Bearbeiten 2: RegExp ist möglicherweise schneller als indexOf, wenn die Zeichenfolgen sehr lang sind und / oder wiederholte Muster enthalten. Siehe Kommentare und die Antwort von @ Felix.

Stephen Chung
quelle
aber wie ist das im vergleich zu anderen methoden? Ist dies die schnellste oder nur eine der vielen Methoden?
Chii
Dies sollte schnell gehen, da es von JavaScript selbst implementiert wird (dh es wird nativer Code ausgeführt). Jede andere auf JavaScript-Code basierende Methode ist langsamer. Wenn Sie die genaue Zeichenfolge kennen, ist ein regulärer Ausdruck möglicherweise etwas schneller (da die JavaScript-Engine die Prototypenkette nicht durchlaufen muss, um .indexOf zu finden).
Stephen Chung
Wenn Sie eine Suche ohne Berücksichtigung der Groß- und Kleinschreibung benötigen, müssen Sie auf jeden Fall ein RegExp-Objekt erstellen und aufrufen test.
Stephen Chung
3
Habe gerade einen Test in Safari durchgeführt. indexOfist eine Größenordnung langsamer als jede andere Methode. Man kann also eigentlich nicht sagen, welche Methode schneller ist. Es variiert von Browser zu Browser.
Felix Kling
@ Felix, das ist eine gute Beobachtung (vertraue niemals etwas, bis du es tatsächlich selbst versuchst)! Ich erinnere mich vage an etwas, das in Strings mit vielen sich wiederholenden Mustern besagt, dass Regex schneller als eine einfache Schleifenvergleichsimplementierung sein sollten, da Regex in Zustandsmaschinen kompiliert werden und viel schneller zurückverfolgen können als einfache Schleifen - was immer zurückgehen muss. Spur zum nächsten Zeichen. +1 für das Experiment und das Herausbringen!
Stephen Chung
17

Die schnellste

  1. (ES6) enthält
    var string = "Hallo",
    Teilzeichenfolge = "lo";
    string.includes (Teilzeichenfolge);
  1. ES5 und älter indexOf
    var string = "Hallo",
    Teilzeichenfolge = "lo";
    string.indexOf (Teilzeichenfolge)! == -1;

http://jsben.ch/9cwLJ

Geben Sie hier die Bildbeschreibung ein

Tính Ngô Quang
quelle
7

Ich habe festgestellt, dass die Verwendung einer einfachen for-Schleife, das Durchlaufen aller Elemente in der Zeichenfolge und das Vergleichen mit charAtdie Leistung schneller als indexOfoder ist Regex. Der Code und der Proof sind bei JSPerf erhältlich .

ETA: indexOfund charAtbeide sind auf Chrome Mobile gemäß den auf jsperf.com aufgeführten Browser Scope-Daten ähnlich schlecht

wpg4665
quelle
Seltsam, dass eine handgemachte Funktion besser ist als eine eingebaute, aber ich denke, das liegt daran, dass die Nadel nur ein Zeichen ist. Immer noch ...
Moss
Getestet in Chrome Mobile 36.0.1985.57 auf Apple iPad (iOS 7.1.1). IndexOf ist schneller. Entschuldigung
rpax
@rpax CharAt ist auf allen Plattformen (basierend auf dem Verlauf von jsperf) immer noch erheblich schneller, mit Ausnahme von Chrome Mobile, wo sowohl IndexOf als auch CharAt im Vergleich zum Desktop gleichermaßen eine sehr schlechte Leistung erbringen.
wpg4665
1
Ich würde gerne sehen, wie dies in NodeJS funktioniert, und dies ist auch kein gutes Beispiel, da Sie nur nach einem Zeichen gegen einen Teilstring suchen.
Qodeninja
Dies ist überhaupt keine gültige Antwort. Sie suchen nicht nach einem Teilstring, sondern nur nach dem Auftreten eines einzelnen Zeichens
Henrik Myntti
7

In ES6 wird die includes()Methode verwendet, um zu bestimmen, ob eine Zeichenfolge in einer anderen Zeichenfolge gefunden werden kann, zurückgegeben trueoder falseentsprechend.

var str = 'To be, or not to be, that is the question.';

console.log(str.includes('To be'));       // true
console.log(str.includes('question'));    // true
console.log(str.includes('nonexistent')); // false

Hier ist jsperf zwischen

var ret = str.includes('one');

Und

var ret = (str.indexOf('one') !== -1);

Wie das in jsperf gezeigte Ergebnis zeigt, scheinen beide eine gute Leistung zu erbringen.

zangw
quelle
Kann ich "Regex" als Argument verwenden? Wie : str.includes("x|y"); Suchen Sie im selben Aufruf nach den Literalen "x" oder "y".
Ptkato
@Patrick, Gemäß dem Include-Dokument können Sie es nicht verwenden regex. Eine str.includes("x") || str.includes('y')
Lösung
Infolge der Chrome 59 JavaScript-Verbesserungen indexOfist deutlich schneller als includes(ab 1600% schneller). Es ist unklar, wie sich ein Unterschied von 44 Millionen Iterationen / Sek. Und 777+ Millionen I / Sek. Auf die Leistung in der realen Welt auswirkt. Mobilgeräte profitieren jedoch wahrscheinlich genug, indexOfum die ideale Wahl zu sein.
Chad Levy
3

Um eine einfache Zeichenfolge zu finden, ist die Verwendung der indexOf () -Methode und der Verwendung von Regex ziemlich identisch: http://jsperf.com/substring - wählen Sie also diejenige aus, die einfacher zu schreiben scheint.

Chii
quelle
1

Es ist eine einfache Möglichkeit, die .match()Methode zum Zeichenfolgen zu verwenden.

var re = /(AND|OR|MAYBE)/;
var str = "IT'S MAYBE BETTER WAY TO USE .MATCH() METHOD TO STRING";
console.log('Do we found something?', Boolean(str.match(re)));

Ich wünsche Ihnen einen schönen Tag, Sir!

Anton Danilchenko
quelle
4
Kein Grund, matchwann es eine testMethode gibt ... Schauen Sie sich die Top-Antwort an.
Bergi