Eine hoffentlich schnellere bidirektionale indexOf
/ lastIndexOf
Alternative
2015
Während die neue Methode enthält, ist sehr nett, aber die Unterstützung ist im Moment Null.
Es ist lange her, dass ich mir überlegt habe, wie ich die langsamen Funktionen indexOf / lastIndexOf ersetzen kann.
Es wurde bereits ein performanter Weg gefunden, der sich die besten Antworten ansieht. Von diesen habe ich die contains
von @Damir Zekic gepostete Funktion ausgewählt, die die schnellste sein sollte. Es heißt aber auch, dass die Benchmarks aus dem Jahr 2008 stammen und daher veraltet sind.
Ich bevorzuge es while
auch for
, aber aus keinem bestimmten Grund habe ich das Schreiben der Funktion mit einer for-Schleife beendet. Es könnte auch mit einem gemacht werden while --
.
Ich war neugierig, ob die Iteration viel langsamer war, wenn ich dabei beide Seiten des Arrays überprüfe. Anscheinend nein, und so ist diese Funktion ungefähr zweimal schneller als die am besten bewerteten. Offensichtlich ist es auch schneller als das native. Dies in einer realen Umgebung, in der Sie nie wissen, ob sich der gesuchte Wert am Anfang oder am Ende des Arrays befindet.
Wenn Sie wissen, dass Sie gerade ein Array mit einem Wert verschoben haben, bleibt die Verwendung von lastIndexOf wahrscheinlich die beste Lösung. Wenn Sie jedoch große Arrays durchlaufen müssen und das Ergebnis überall sein kann, kann dies eine solide Lösung sein, um die Dinge schneller zu machen.
Bidirektionaler IndexOf / lastIndexOf
function bidirectionalIndexOf(a, b, c, d, e){
for(c=a.length,d=c*1; c--; ){
if(a[c]==b) return c; //or this[c]===b
if(a[e=d-1-c]==b) return e; //or a[e=d-1-c]===b
}
return -1
}
//Usage
bidirectionalIndexOf(array,'value');
Leistungstest
http://jsperf.com/bidirectionalindexof
Als Test habe ich ein Array mit 100.000 Einträgen erstellt.
Drei Abfragen: am Anfang, in der Mitte und am Ende des Arrays.
Ich hoffe, Sie finden das auch interessant und testen die Leistung.
Hinweis: Wie Sie sehen, habe ich die contains
Funktion geringfügig geändert , um die Ausgabe von indexOf & lastIndexOf widerzuspiegeln (also im Grunde genommen true
mit index
und false
mit -1
). Das sollte nicht schaden.
Die Array-Prototyp-Variante
Object.defineProperty(Array.prototype,'bidirectionalIndexOf',{value:function(b,c,d,e){
for(c=this.length,d=c*1; c--; ){
if(this[c]==b) return c; //or this[c]===b
if(this[e=d-1-c] == b) return e; //or this[e=d-1-c]===b
}
return -1
},writable:false, enumerable:false});
// Usage
array.bidirectionalIndexOf('value');
Die Funktion kann auch leicht geändert werden, um true oder false oder sogar das Objekt, die Zeichenfolge oder was auch immer zurückzugeben.
Und hier ist die while
Variante:
function bidirectionalIndexOf(a, b, c, d){
c=a.length; d=c-1;
while(c--){
if(b===a[c]) return c;
if(b===a[d-c]) return d-c;
}
return c
}
// Usage
bidirectionalIndexOf(array,'value');
Wie ist das möglich?
Ich denke, dass die einfache Berechnung, um den reflektierten Index in einem Array zu erhalten, so einfach ist, dass sie zweimal schneller ist als eine tatsächliche Schleifeniteration.
Hier ist ein komplexes Beispiel, das drei Überprüfungen pro Iteration durchführt. Dies ist jedoch nur mit einer längeren Berechnung möglich, die zu einer Verlangsamung des Codes führt.
http://jsperf.com/bidirectionalindexof/2