Un bidirezionale indexOf
/ lastIndexOf
alternativa si spera più veloce
2015
Mentre il nuovo metodo include è molto bello, il supporto è praticamente zero per ora.
È da molto tempo che pensavo al modo di sostituire le funzioni slow indexOf / lastIndexOf.
È già stato trovato un modo performante, guardando le risposte migliori. Tra quelli ho scelto la contains
funzione pubblicata da @Damir Zekic che dovrebbe essere la più veloce. Ma afferma anche che i parametri di riferimento sono del 2008 e quindi sono obsoleti.
Preferisco anche while
over for
, ma per un motivo non specifico ho finito di scrivere la funzione con un ciclo for. Potrebbe anche essere fatto con awhile --
.
Ero curioso di sapere se l'iterazione era molto più lenta se controllo entrambi i lati dell'array mentre lo faccio. Apparentemente no, e quindi questa funzione è circa due volte più veloce di quelle più votate. Ovviamente è anche più veloce di quello nativo. Questo in un ambiente del mondo reale, dove non si sa mai se il valore che si sta cercando è all'inizio o alla fine dell'array.
Quando sai che hai appena spinto un array con un valore, usare lastIndexOf rimane probabilmente la soluzione migliore, ma se devi viaggiare attraverso grandi array e il risultato potrebbe essere ovunque, questa potrebbe essere una soluzione solida per rendere le cose più veloci.
Indice bidirezionaleOf / 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');
Test della prestazione
http://jsperf.com/bidirectionalindexof
Come test ho creato un array con 100k voci.
Tre query: all'inizio, al centro e alla fine dell'array.
Spero che anche tu lo trovi interessante e testare le prestazioni.
Nota: Come puoi vedere, ho leggermente modificato la contains
funzione per riflettere l'output indexOf e lastIndexOf (quindi sostanzialmente true
con index
e false
con -1
). Questo non dovrebbe danneggiarlo.
La variante del prototipo di array
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');
La funzione può anche essere facilmente modificata per restituire vero o falso o persino l'oggetto, la stringa o qualunque cosa sia.
Ed ecco la 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');
Com'è possibile?
Penso che il semplice calcolo per ottenere l'indice riflesso in un array sia così semplice che è due volte più veloce rispetto a eseguire un'iterazione di loop effettiva.
Ecco un esempio complesso che esegue tre controlli per iterazione, ma ciò è possibile solo con un calcolo più lungo che provoca il rallentamento del codice.
http://jsperf.com/bidirectionalindexof/2