Gibt es in Javascript ein Äquivalent zu String.indexOf (), das einen regulären Ausdruck anstelle eines Strings für den ersten ersten Parameter verwendet und dennoch einen zweiten Parameter zulässt?
Ich muss so etwas tun
str.indexOf(/[abc]/ , i);
und
str.lastIndexOf(/[abc]/ , i);
Während String.search () einen regulären Ausdruck als Parameter verwendet, kann ich kein zweites Argument angeben!
Bearbeiten:
Dies stellte sich als schwieriger heraus, als ich ursprünglich gedacht hatte. Deshalb habe ich eine kleine Testfunktion geschrieben, um alle bereitgestellten Lösungen zu testen. Es wird davon ausgegangen, dass dem String-Objekt regexIndexOf und regexLastIndexOf hinzugefügt wurden.
function test (str) {
var i = str.length +2;
while (i--) {
if (str.indexOf('a',i) != str.regexIndexOf(/a/,i))
alert (['failed regexIndexOf ' , str,i , str.indexOf('a',i) , str.regexIndexOf(/a/,i)]) ;
if (str.lastIndexOf('a',i) != str.regexLastIndexOf(/a/,i) )
alert (['failed regexLastIndexOf ' , str,i,str.lastIndexOf('a',i) , str.regexLastIndexOf(/a/,i)]) ;
}
}
und ich teste wie folgt, um sicherzustellen, dass mindestens für einen regulären Regexp das Ergebnis das gleiche ist, als ob wir indexOf verwendet hätten
// Suche das a unter den xes
test ('xxx');
Test ('Axx');
Test ('xax');
Test ('xxa');
Test ('Axa');
Test ('xaa');
Test ('aax');
Test ('aaa');
quelle
|
Innen[ ]
entspricht dem wörtlichen Zeichen|
. Du hast es wahrscheinlich gemeint[abc]
.Antworten:
Wenn ich einige der bereits erwähnten Ansätze kombiniere (der indexOf ist offensichtlich ziemlich einfach), denke ich, dass dies die Funktionen sind, die den Trick machen:
Das Ändern des integrierten String-Objekts würde natürlich für die meisten Menschen rote Fahnen setzen, aber dies kann ein Mal sein, wenn es keine so große Sache ist. sei dir dessen einfach bewusst.
UPDATE: Bearbeitet,
regexLastIndexOf()
so dass eslastIndexOf()
jetzt zu imitieren scheint . Bitte lassen Sie mich wissen, ob und unter welchen Umständen dies immer noch fehlschlägt.UPDATE: Besteht alle Tests, die in den Kommentaren auf dieser Seite gefunden wurden, und meine eigenen. Das heißt natürlich nicht, dass es kugelsicher ist. Jedes Feedback wird geschätzt.
quelle
regexLastIndexOf
geben nur den Index der letzten nicht überlappenden Übereinstimmung zurück.regex.lastIndex = result.index + 1;
anstattregex.lastIndex = ++nextStop;
. Es wird hoffentlich viel schneller zum nächsten Spiel übergehen, ohne dass ein Ergebnis verloren geht.Instanzen des
String
Konstruktors verfügen über eine.search()
Methode, die ein RegExp akzeptiert und den Index der ersten Übereinstimmung zurückgibt.Um die Suche von einer bestimmten Position aus zu starten (indem Sie den zweiten Parameter von vortäuschen
.indexOf()
), könnenslice
Sie die ersteni
Zeichen deaktivieren :Dadurch wird der Index jedoch in der kürzeren Zeichenfolge angezeigt (nachdem der erste Teil abgeschnitten wurde), sodass Sie die Länge des abgeschnittenen Teils (
i
) zum zurückgegebenen Index hinzufügen möchten, wenn dies nicht der Fall ist-1
. Dadurch erhalten Sie den Index in der ursprünglichen Zeichenfolge:quelle
function regexIndexOf(text, offset) { var initial = text.substr(offset).search(/re/); if(initial >= 0) { initial += offset; } return initial; }
Ich habe eine kurze Version für dich. Es funktioniert gut für mich!
Und wenn Sie eine Prototypversion wollen:
BEARBEITEN : Wenn Sie Unterstützung für fromIndex hinzufügen möchten
So einfach ist das:
quelle
startIndex
Parameter wie gewohnt zu übernehmenindeoxOf
und zulastIndexOf
tun.startIndex
(oderfromIndex
) bearbeitet . Ich hoffe es hilft!lastIndexOfRegex
sollte auch den Wert vonfromIndex
zum Ergebnis zurückaddieren."aRomeo Romeo".indexOfRegex(new RegExp("\\bromeo", 'gi'));
Das Ergebnis ist 1, wenn es 7 sein sollte, da indexOf zum ersten Mal nach dem "Romeo" sucht, unabhängig davon, ob es am Anfang eines Wortes steht oder nicht.Verwenden:
Siehe die Dokumentation hier.
quelle
0
und sieben Jahre später veröffentlicht wurde.Basierend auf der Antwort von BaileyP. Der Hauptunterschied besteht darin, dass diese Methoden zurückgegeben werden,
-1
wenn das Muster nicht übereinstimmt.Edit: Dank der Antwort von Jason Bunting habe ich eine Idee. Warum nicht die
.lastIndex
Eigenschaft des regulären Ausdrucks ändern ? Dies funktioniert jedoch nur für Muster mit dem globalen Flag (/g
).Bearbeiten: Aktualisiert, um die Testfälle zu bestehen.
quelle
Sie könnten substr verwenden.
quelle
RexExp
Instanzen haben bereits eine lastIndex- Eigenschaft (wenn sie global sind). Ich kopiere also den regulären Ausdruck, ändere ihn leicht, um ihn unseren Zwecken anzupassen, setzeexec
ihn in die Zeichenfolge und schaue auf dielastIndex
. Dies ist unweigerlich schneller als das Schleifen der Zeichenfolge. (Sie haben genug Beispiele, wie Sie dies auf den String-Prototyp setzen können, oder?)Sie können die Funktionen auch als Prototyp für das RegExp-Objekt erstellen:
Eine kurze Erklärung, wie ich das ändere
RegExp
: DennindexOf
ich muss nur sicherstellen, dass das globale Flag gesetzt ist. FürlastIndexOf
of verwende ich einen negativen Look-Ahead, um das letzte Vorkommen zu finden, es sei denn, dasRegExp
stimmte bereits am Ende der Zeichenfolge überein.quelle
Es ist nicht nativ, aber Sie können diese Funktionalität sicherlich hinzufügen
Ich habe diese Methoden nicht vollständig getestet, aber sie scheinen bisher zu funktionieren.
quelle
Nachdem alle vorgeschlagenen Lösungen meine Tests auf die eine oder andere Weise nicht bestanden haben (bearbeiten: Einige wurden aktualisiert, um die Tests zu bestehen, nachdem ich dies geschrieben habe), fand ich die Mozilla-Implementierung für Array.indexOf und Array.lastIndexOf
Ich habe diese verwendet, um meine Version von String.prototype.regexIndexOf und String.prototype.regexLastIndexOf wie folgt zu implementieren:
Sie scheinen die Testfunktionen zu bestehen, die ich in der Frage angegeben habe.
Natürlich funktionieren sie nur, wenn der reguläre Ausdruck mit einem Zeichen übereinstimmt, aber das reicht für meinen Zweck aus, da ich ihn für Dinge wie ([abc], \ s, \ W, \ D) verwenden werde.
Ich werde die Frage weiter überwachen, falls jemand eine bessere / schnellere / sauberere / allgemeinere Implementierung bereitstellt, die mit jedem regulären Ausdruck funktioniert.
quelle
Ich brauchte eine
regexIndexOf
Funktion auch für ein Array, also habe ich selbst eine programmiert. Ich bezweifle jedoch, dass es optimiert ist, aber ich denke, es sollte richtig funktionieren.quelle
In bestimmten einfachen Fällen können Sie Ihre Rückwärtssuche mithilfe von split vereinfachen.
Dies hat einige schwerwiegende Probleme:
Aber auf der positiven Seite ist es viel weniger Code. Für einen regulären Ausdruck mit konstanter Länge, der sich nicht überlappen kann (wie
/\s\w/
zum Auffinden von Wortgrenzen), ist dies gut genug.quelle
Bei Daten mit geringen Übereinstimmungen ist die Verwendung von string.search in allen Browsern am schnellsten. Bei jeder Iteration wird eine Zeichenfolge neu aufgeteilt:
Für dichte Daten habe ich das gemacht. Es ist komplex im Vergleich zur Ausführungsmethode, aber für dichte Daten ist es 2-10x schneller als jede andere Methode, die ich ausprobiert habe, und ungefähr 100x schneller als die akzeptierte Lösung. Die Hauptpunkte sind:
Der neue reguläre Ausdruck wird ausgeführt und die Ergebnisse von diesem oder dem ersten Exec werden zurückgegeben.
jsPerf von Methoden
Ich verstehe den Zweck der Tests oben nicht. Situationen, die eine Regex erfordern, können nicht mit einem Aufruf von indexOf verglichen werden, was meiner Meinung nach der Grund ist, die Methode überhaupt erst zu entwickeln. Um den Test zu bestehen, ist es sinnvoller, 'xxx + (?! X)' zu verwenden, als die Art und Weise anzupassen, in der der Regex iteriert.
quelle
Der letzte Index von Jason Bunting funktioniert nicht. Meins ist nicht optimal, aber es funktioniert.
quelle
Es gibt noch keine nativen Methoden, die die angeforderte Aufgabe ausführen.
Hier ist der Code, den ich verwende. Es ahmt das Verhalten von String.prototype.indexOf und String.prototype.lastIndexOf nach Methoden , akzeptiert jedoch zusätzlich zu einer Zeichenfolge, die den zu suchenden Wert darstellt, auch RegExp als .
Ja, es dauert ziemlich lange, bis eine Antwort vorliegt, da versucht wird, die aktuellen Standards so genau wie möglich zu befolgen, und natürlich eine angemessene Menge an JSDOC enthält Kommentaren enthält. Einmal minimiert, ist der Code jedoch nur 2,27 KB groß und einmal für die Übertragung komprimiert, sind es nur 1023 Bytes.
Die 2 Methoden, die dadurch hinzugefügt werden
String.prototype
(unter Verwendung von Object.defineProperty , sofern verfügbar), sind:searchOf
searchLastOf
Es besteht alle Tests, die das OP veröffentlicht hat, und außerdem habe ich die Routinen im täglichen Gebrauch ziemlich gründlich getestet und versucht, sicherzustellen, dass sie in mehreren Umgebungen funktionieren, aber Feedback / Probleme sind immer willkommen.
quelle
Wenn Sie nach einer sehr einfachen lastIndex-Suche mit RegExp suchen und es Ihnen egal ist, ob sie lastIndexOf bis ins letzte Detail nachahmt, kann dies Ihre Aufmerksamkeit erregen.
Ich kehre einfach die Zeichenfolge um und subtrahiere den ersten Vorkommensindex von der Länge - 1. Er besteht meinen Test, aber ich denke, dass bei langen Zeichenfolgen ein Leistungsproblem auftreten kann.
quelle
Ich habe verwendet,
String.prototype.match(regex)
was ein String-Array aller gefundenen Übereinstimmungen derregex
in der String angegebenen Werte zurückgibt (weitere Informationen siehe hier ):quelle
Verwenden Sie reguläre Standardausdrücke:
quelle
Nun, da Sie nur versuchen, die Position eines Charakters zu erreichen , ist Regex möglicherweise übertrieben.
Ich nehme an, alles, was Sie wollen, ist, anstatt "zuerst diesen Charakter zu finden", nur den ersten dieser Charaktere zu finden.
Dies ist natürlich die einfache Antwort, macht aber das, was Ihre Frage vorsieht, allerdings ohne den Regex-Teil (weil Sie nicht geklärt haben, warum es speziell ein Regex sein musste).
quelle