Eine hoffentlich schnellere bidirektionale indexOf
/ lastIndexOf
alternativ
2015
Während die neue Methode includes
ist sehr schön, aber die Unterstützung ist im Moment gleich Null.
Ich habe lange darüber nachgedacht, wie ich das langsame indexOf
/ lastIndexOf
Funktionen.
Ein leistungsfähiger Weg wurde bereits gefunden, wenn man sich die wichtigsten Antworten ansieht. Von diesen wählte ich die contains
Funktion von @Damir Zekic, die die schnellste sein sollte. Es heißt aber auch, dass die Benchmarks aus dem Jahr 2008 stammen und daher veraltet sind.
Ich bevorzuge auch while
über for
aber aus keinem bestimmten Grund habe ich die Funktion mit einer for-Schleife geschrieben. Man könnte es auch mit einer while --
.
Ich war neugierig, ob die Iteration war viel langsamer, wenn ich beide Seiten des Arrays überprüfen, während es tun. Offenbar nicht, und so ist diese Funktion etwa zwei Mal schneller als die oben genannten. Offensichtlich ist sie auch schneller als die native Funktion. Dies geschieht in einer realen Umgebung, in der man nie weiß, ob der gesuchte Wert am Anfang oder am Ende des Arrays liegt.
Wenn man weiß, dass man gerade ein Array mit einem Wert gepusht hat, bleibt die Verwendung von lastIndexOf wahrscheinlich die beste Lösung, aber wenn man durch große Arrays reisen muss und das Ergebnis überall sein könnte, könnte dies eine solide Lösung sein, um Dinge schneller zu machen.
Bidirektional 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
https://jsbench.me/7el1b8dj80
Zu Testzwecken habe ich ein Array mit 100k Einträgen erstellt.
Drei Abfragen: am Anfang, in der Mitte und am Ende der Reihe.
Ich hoffe, Sie finden das auch interessant und testen die Leistung.
Anmerkung: Wie Sie sehen können, habe ich die contains
Funktion, um die indexOf
& lastIndexOf
Ausgabe (also grundsätzlich true
mit dem index
y false
con -1
). Das sollte ihm nicht schaden.
Die Variante des Array-Prototyps
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, den String 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 zwei Mal schneller ist als eine tatsächliche Schleifeniteration.
Hier ist ein komplexes Beispiel, bei dem drei Prüfungen pro Iteration durchgeführt werden, was aber nur mit einer längeren Berechnung möglich ist, die die Verlangsamung des Codes verursacht.
https://web.archive.org/web/20151019160219/http://jsperf.com/bidirectionalindexof/2
65 Stimmen
Gerade getestet: Ihr Weg ist tatsächlich der schnellste für alle Browser: jsperf.com/find-element-in-obj-vs-array/2 (abgesehen von der Vorabspeicherung von a.length in einer Variablen), während die Verwendung von indexOf (wie in $.inArray) viel langsamer ist
23 Stimmen
Viele haben geantwortet, dass die Array#indexOf ist Ihre beste Wahl hier. Aber wenn Sie etwas wollen, das korrekt in Boolean umgewandelt werden kann, verwenden Sie dies:
~[1,2,3].indexOf(4)
wird 0 zurückgeben, was als falsch ausgewertet wird, während~[1,2,3].indexOf(3)
wird -3 zurückgeben, was als wahr ausgewertet wird.13 Stimmen
~
ist nicht das, was Sie für die Konvertierung in einen Booleschen Wert verwenden wollen, dafür brauchen Sie!
. Aber in diesem Fall wollen Sie die Gleichheit mit -1 prüfen, damit die Funktion nicht endetreturn [1,2,3].indexOf(3) === -1;
~
nicht binär ist, wird jedes Bit des Wertes einzeln invertiert.1 Stimmen
IE9 unterstützt
indexOf()
gemäß w3schools.com/jsref/jsref_indexof_array.asp . Wenn ältere Browser besser Ansatz ist, zu definierenprototype
paraindexOf()
Funktion, wie sie in Array.indexOf im Internet Explorer19 Stimmen
@Iordvlad
[1,2,3].indexOf(4)
wird tatsächlich Rückgabe -1 . Wie @mcfedr feststellte,~
ist die bitweise-NOT-Operator siehe ES5 11.4.8. Da die binäre Darstellung von-1
nur aus 1en besteht, ist sein Komplement0
die als falsch ausgewertet wird. Das Komplement einer beliebigen anderen Zahl ist ungleich Null, also wahr. Also,~
funktioniert einwandfrei und wird häufig in Verbindung mitindexOf
.9 Stimmen
Der Titel ist irreführend. Wo ist die
[[1,2],[3,4]].includes([3,4])
?1 Stimmen
@brad, wenn ich zum ersten Mal lesen Sie Ihre Frage, ich konnte nicht verstehen, Ihre Idee, ein Objekt hier ist Javascript-Objekt oder ein primitiver Wert. Angenommen, ich habe ein Array:
const arr = [1, 2, 3, { foo: 1}];
. Undarr.includes(1) // true
sondernarr.includes({ foo: 1 }) //false
1 Stimmen
Wenn die Elemente in Ihrem Array Objekte sind dann schauen Sie sich este Antwort, die die
some
Funktion.0 Stimmen
let arr = ['apple','banana', 1, 2, 4] if (!arr.includes('banana') ) console.log('No') else console.log('Yes')
0 Stimmen
Console.log(['joe', 'jane', 'mary'].includes('jane'));