JavaScript: indexOf vs. Match beim Suchen von Strings?
Lesezeit: 9 Minuten
Indra
Abgesehen von der Lesbarkeit, gibt es erkennbare Unterschiede (möglicherweise bei der Leistung) zwischen der Verwendung von
str.indexOf("src")
und
str.match(/src/)
Ich persönlich bevorzuge match (und regexp), aber die Kollegen scheinen den anderen Weg zu gehen. Wir haben uns gefragt, ob es wichtig ist …?
BEARBEITEN:
Ich hätte eingangs sagen sollen, dass dies für Funktionen gilt, die einen teilweisen Abgleich von einfachen Zeichenfolgen durchführen (um Bezeichner in Klassenattributen für JQuery abzurufen), anstatt vollständige Regexp-Suchen mit Platzhaltern usw.
Ich finde str.indexOf("xyz") verglichen werden soll /xyz/.test(str)
– Redu
9. Juni 2016 um 5:12 Uhr
hier ein Benchmark, der indexOf, regex und match vergleicht jsben.ch/#/r9hBp
– EscapeNetscape
21. Oktober 2016 um 22:02 Uhr
Eigentlich String.prototype.indexOf eher vergleichbar ist String.prototype.search da beide den Startindex des Spiels zurückgeben. Der boolesche Ausdruck 'foo'.indexOf('bar') !== -1 ist besser vergleichbar mit /bar/.test('foo') weil beide einen booleschen Wert ergeben. Für einfache Ausdrücke ohne Gruppen und Anker sollte die Leistung jedoch vergleichbar sein. str.match verschwendet zu viel, weil es alle Übereinstimmungen zurückgibt, und ich würde davon abraten, es für Vergleiche zu verwenden. Das heißt, wenn Sie kein Leistungsproblem haben, wählen Sie das besser lesbare.
– Thorsten Walter
10. Januar 2019 um 10:00 Uhr
RegExp ist tatsächlich langsamer als indexOf (man sieht es hier), obwohl dies normalerweise kein Problem sein sollte. Bei RegExp müssen Sie auch sicherstellen, dass die Zeichenfolge richtig maskiert ist, was eine zusätzliche Sache ist, über die Sie nachdenken müssen.
Abgesehen von diesen beiden Problemen, wenn zwei Tools genau das tun, was Sie brauchen, warum wählen Sie dann nicht das einfachere?
Macht für mich Sinn, von nun an werden wir mit laufen indexOf sofern keine zusätzliche RegExp-Funktionalität erforderlich ist. Danke vielmals! PS. Die konfigurierbare Testseite, auf die Sie in Ihrer Antwort verlinkt haben, ist cool – ist sie öffentlich zugänglich oder etwas, das Sie sich selbst ausgedacht haben?
– Indra
21. Januar 2011 um 11:12 Uhr
@5arx, jsperf ist wie jsfiddle ein unverzichtbares Tool zum schnellen Testen von Ideen. Es ist eine öffentliche Seite, gehen Sie einfach zu jsperf.com und erstellen Sie Ihre eigenen Tests.
– David Tang
21. Januar 2011 um 11:15 Uhr
Laut diesem jsperf-Test stimmt es einfach nicht, dass indexOf immer schnell ist: stackoverflow.com/a/5296314/981933
– F. Lekschas
8. Oktober 2013 um 7:17 Uhr
Der Test, auf den Sie sich beziehen, kann genau sein oder auch nicht – er hat mit Sicherheit den RegExp falsch gemacht, was kein Vertrauen weckt. '[\\?|&]' sollte sein [?&] entweder passen ? oder & – keine Notwendigkeit für ein | Betreiber, noch das Entkommen der ?.
– Lee Goddard
2. März 2016 um 8:38 Uhr
Nur um historische Farbe hinzuzufügen: Zum Datum dieses Kommentars sagt der in der Antwort verlinkte Test auf meinem Computer (2017 MBP mit Chrome 56.0.2924 unter Mac OS X 10.12.3), dass die indexOf ist 12 % langsamer als der Regex-Match. Bei vielen Dingen lautet die richtige Antwort also wohl: Es kommt darauf an.
– davemyron
20. März 2017 um 21:17 Uhr
Tim Pietzcker
Ihr Vergleich ist möglicherweise nicht ganz fair. indexOf wird mit glatten Saiten verwendet und ist daher sehr schnell; match nimmt einen regulären Ausdruck – natürlich kann es im Vergleich langsamer sein, aber wenn Sie einen Regex-Match machen wollen, werden Sie damit nicht weit kommen indexOf. Andererseits können Engines für reguläre Ausdrücke optimiert werden und haben sich in den letzten Jahren in ihrer Leistung verbessert.
In Ihrem Fall, wo Sie nach einer wörtlichen Zeichenfolge suchen, indexOf sollte ausreichen. Es gibt jedoch immer noch eine Anwendung für reguläre Ausdrücke: Wenn Sie übereinstimmen müssen gesamte Wörter und möchten übereinstimmende Teilzeichenfolgen vermeiden, dann geben Ihnen reguläre Ausdrücke “Wortgrenzenanker”. Zum Beispiel:
indexOf('bar')
wird finden bar dreimal drin bar, fubar, barmywohingegen
match(/\bbar\b/)
wird nur passen bar wenn es nicht Teil eines längeren Wortes ist.
Wie Sie in den Kommentaren sehen können, wurden einige Vergleiche durchgeführt, die zeigen, dass eine Regex möglicherweise schneller ist als indexOf – Wenn es leistungskritisch ist, müssen Sie Ihren Code möglicherweise profilieren.
Ich hielt es für eine faire Frage, die aus einem Perl-Hintergrund stammt, wo eine äquivalente Regex schneller ist als indexOf.
– Lee Goddard
2. März 2016 um 8:39 Uhr
Es ist kein Vergleich zwischen Äpfeln und Birnen, da eine triviale Regex so schnell wie möglich optimiert werden kann indexOf. Ich bin gerade gelaufen jsperf.com/substring-test und es behauptet, dass “regex case insensitive” am schnellsten und 30% schneller ist als “indexOf”, was ich nicht glauben möchte.
– maaartinus
29. Mai 2017 um 1:45 Uhr
Während indexOf jede dieser Zeichenfolgen finden würde, findet es nur den ersten „Balken“ in der Zeichenfolge.
– PRMan
21. Juni um 15:12 Uhr
Hier alle Möglichkeiten (relativ), nach Strings zu suchen
// 1. beinhaltet (eingeführt in ES6)
var string = "string to search for substring",
substring = "sea";
string.includes(substring);
// 2. string.indexOf
var string = "string to search for substring",
substring = "sea";
string.indexOf(substring) !== -1;
// 3. RegExp: test
var string = "string to search for substring",
expr = /sea/; // no quotes here
expr.test(string);
// 4. string.übereinstimmung
var string = "string to search for substring",
expr = "/sea/";
string.match(expr);
//5. Zeichenfolge.Suche
var string = "string to search for substring",
expr = "/sea/";
string.search(expr);
Benchmarks scheinen speziell für es6-Includes verdreht zu sein, lesen Sie die Kommentare.
Zusammenfassend:
wenn Sie die Streichhölzer nicht brauchen. => Entweder Sie brauchen Regex und verwenden es so Prüfung. Sonst es6 beinhaltet oder Index von. Still Prüfung vs Index von sind nahe.
Und für meinen eigenen Benchmark-Test. Hier ist es http://jsben.ch/fFnA0
Sie können es testen (es ist browserabhängig) [test multiple time]
Hier, wie es funktioniert hat (mehrere Läufe indexOf und enthält einen Schlag gegen den anderen, und sie sind nah dran). Sie sind also gleich. [here using the same test platform as the article above].
Beachten Sie, dass jsben.ch den Speicherüberlauf nicht handhabt (oder es gibt keine korrekten Grenzen. Es wird keine Meldung angezeigt), sodass das Ergebnis falsch werden kann, wenn Sie mehr als 8 Textduplizierungen hinzufügen (8 funktionieren gut). Aber die Schlussfolgerung ist, dass bei sehr großem Text alle drei auf die gleiche Weise funktionieren. Ansonsten sind kurz indexOf und Includes gleich und testen etwas langsamer. oder Kann das gleiche sein, wie es in Chrome schien (Firefox 60 ist langsamer).
Hinweis bei jsben.ch: Nicht ausflippen, wenn Sie ein inkonsistentes Ergebnis erhalten. Probieren Sie eine andere Zeit aus und sehen Sie, ob sie konsistent ist oder nicht. Browser wechseln, manchmal laufen sie einfach total falsch. Fehler oder schlechte Handhabung des Speichers. Oder so.
ex:
Auch hier mein Benchmark zu jsperf (bessere Details und handhabbare Grafiken für mehrere Browser)
Hinweis: über den Benchmark oben. Für die sehr kurze Saite Version (jsperf) hatte einen großen Fehler für Chrome. Mit meinen Augen sehen. Etwa 60 Samples wurden sowohl für indexOf als auch für include auf die gleiche Weise ausgeführt (viele Male wiederholt). Und teste ein bisschen weniger und damit langsamer. Lassen Sie sich nicht mit dem falschen Diagramm täuschen. Es ist eindeutig falsch. Gleiche Testarbeit ok für Firefox, sicher ist es ein Fehler.
Hier die Illustration: (das erste Bild war der Test auf Firefox)
waaaa. Plötzlich wurde indexOf zu Superman. Aber wie gesagt, ich habe den Test gemacht und mir die Anzahl der Samples angesehen, die ungefähr 60 waren. Sowohl indexOf als auch include und sie haben die gleiche Leistung erbracht. Ein Fehler an jspref. Abgesehen von diesem (vielleicht wegen eines Problems mit Speicherbeschränkungen) war der Rest konsistent, es gibt mehr Details. Und Sie sehen, wie viele einfache Dinge in Echtzeit passieren.
Endgültiger Lebenslauf
indexOf vs enthält => Gleiche Leistung
Prüfung => kann für kurze Zeichenfolgen oder Text langsamer sein. Und das gleiche bei langen Texten. Und es macht Sinn für den Overhead, den die Regex-Engine hinzufügt. In Chrom schien es überhaupt keine Rolle zu spielen.
:daumen hoch: für die mühe 🙂
– Ajay Kumar Ganesh
12. April 2019 um 14:27 Uhr
Wenn Sie versuchen, nach Vorkommen von Teilzeichenfolgen zu suchen case-insensitive dann match scheint schneller zu sein als eine Kombination aus indexOf und toLowerCase()
Du fragst ob str.indexOf('target') oder str.match(/target/) sollte bevorzugt werden. Wie andere Poster angedeutet haben, sind die Anwendungsfälle und Rückgabetypen dieser Methoden unterschiedlich. Der erste fragt: „wo in str kann ich zuerst finden 'target'?” Der zweite fragt. “Tut str stimmen mit der Regex überein, und wenn ja, wie lauten alle Übereinstimmungen für alle zugehörigen Capture-Gruppen?”
Das Problem ist, dass keines der beiden technisch dafür ausgelegt ist, die einfachere Frage zu stellen: “Enthält die Zeichenfolge die Teilzeichenfolge?” Es gibt etwas, das explizit dafür vorgesehen ist:
var doesStringContainTarget = /target/.test(str);
Die Verwendung hat mehrere Vorteile regex.test(string):
Es gibt einen booleschen Wert zurück, was Sie interessiert
Es ist leistungsfähiger als str.match(/target/) (und Konkurrenten str.indexOf('target'))
Wenn aus irgendeinem Grund str ist undefined oder nullDu wirst kriegen false (das gewünschte Ergebnis) anstatt a zu werfen TypeError
Lukas H
Verwenden indexOf sollte theoretisch schneller sein als eine Regex, wenn Sie nur nach einfachem Text suchen, aber Sie sollten selbst einige vergleichende Benchmarks durchführen, wenn Sie sich Sorgen um die Leistung machen.
Wenn Sie es vorziehen match und es ist schnell genug für Ihre Bedürfnisse, dann machen Sie es.
Für das, was es wert ist, stimme ich Ihren Kollegen darin zu: Ich würde verwenden indexOf bei der Suche nach einer einfachen Zeichenfolge und verwenden match etc nur, wenn ich die zusätzliche Funktionalität benötige, die durch reguläre Ausdrücke bereitgestellt wird.
ChaosPandion
Leistungsmäßig indexOf wird zumindest etwas schneller sein als match. Auf die konkrete Umsetzung kommt es an. Stellen Sie sich bei der Entscheidung, welche Sie verwenden möchten, die folgende Frage:
Reicht ein ganzzahliger Index oder benötige ich die Funktionalität eines RegExp-Match-Ergebnisses?
10822100cookie-checkJavaScript: indexOf vs. Match beim Suchen von Strings?yes
Ich finde
str.indexOf("xyz")
verglichen werden soll/xyz/.test(str)
– Redu
9. Juni 2016 um 5:12 Uhr
hier ein Benchmark, der indexOf, regex und match vergleicht jsben.ch/#/r9hBp
– EscapeNetscape
21. Oktober 2016 um 22:02 Uhr
Eigentlich
String.prototype.indexOf
eher vergleichbar istString.prototype.search
da beide den Startindex des Spiels zurückgeben. Der boolesche Ausdruck'foo'.indexOf('bar') !== -1
ist besser vergleichbar mit/bar/.test('foo')
weil beide einen booleschen Wert ergeben. Für einfache Ausdrücke ohne Gruppen und Anker sollte die Leistung jedoch vergleichbar sein.str.match
verschwendet zu viel, weil es alle Übereinstimmungen zurückgibt, und ich würde davon abraten, es für Vergleiche zu verwenden. Das heißt, wenn Sie kein Leistungsproblem haben, wählen Sie das besser lesbare.– Thorsten Walter
10. Januar 2019 um 10:00 Uhr