Il modo migliore per trovare se un elemento si trova in un array JavaScript?

Qual è il modo migliore per trovare se un object si trova in un array?

Questo è il modo migliore che conosco:

function include(arr, obj) { for(var i=0; i<arr.length; i++) { if (arr[i] == obj) return true; } } include([1,2,3,4], 3); // true include([1,2,3,4], 6); // undefined 

A partire da ECMAScript 2016 puoi usare includes()

 arr.includes(obj); 

Se si desidera supportare IE o altri browser più vecchi:

 function include(arr,obj) { return (arr.indexOf(obj) != -1); } 

EDIT: Questo non funzionerà su IE6, 7 o 8 però. La soluzione migliore è definirla autonomamente se non è presente:

  1. Versione di Mozilla (ECMA-262):

      if (!Array.prototype.indexOf) { Array.prototype.indexOf = function(searchElement /*, fromIndex */) { "use strict"; if (this === void 0 || this === null) throw new TypeError(); var t = Object(this); var len = t.length >>> 0; if (len === 0) return -1; var n = 0; if (arguments.length > 0) { n = Number(arguments[1]); if (n !== n) n = 0; else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) n = (n > 0 || -1) * Math.floor(Math.abs(n)); } if (n >= len) return -1; var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0); for (; k < len; k++) { if (k in t && t[k] === searchElement) return k; } return -1; }; } 
  2. La versione di Daniel James :

     if (!Array.prototype.indexOf) { Array.prototype.indexOf = function (obj, fromIndex) { if (fromIndex == null) { fromIndex = 0; } else if (fromIndex < 0) { fromIndex = Math.max(0, this.length + fromIndex); } for (var i = fromIndex, j = this.length; i < j; i++) { if (this[i] === obj) return i; } return -1; }; } 
  3. la versione di roosteronacid :

     Array.prototype.hasObject = ( !Array.indexOf ? function (o) { var l = this.length + 1; while (l -= 1) { if (this[l - 1] === o) { return true; } } return false; } : function (o) { return (this.indexOf(o) !== -1); } ); 

Se stai usando jQuery:

 $.inArray(5 + 5, [ "8", "9", "10", 10 + "" ]); 

Per maggiori informazioni: http://api.jquery.com/jQuery.inArray/

Innanzitutto, implementa indexOf in JavaScript per i browser che non lo hanno già. Ad esempio, vedi gli extra di Erik Arvidsson (anche il post del blog associato ). E poi puoi usare indexOf senza preoccuparti del supporto del browser. Ecco una versione leggermente ottimizzata della sua implementazione indexOf :

 if (!Array.prototype.indexOf) { Array.prototype.indexOf = function (obj, fromIndex) { if (fromIndex == null) { fromIndex = 0; } else if (fromIndex < 0) { fromIndex = Math.max(0, this.length + fromIndex); } for (var i = fromIndex, j = this.length; i < j; i++) { if (this[i] === obj) return i; } return -1; }; } 

È cambiato per memorizzare la lunghezza in modo che non abbia bisogno di cercarlo ogni iterazione. Ma la differenza non è enorme. Una funzione meno generica potrebbe essere più veloce:

 var include = Array.prototype.indexOf ? function(arr, obj) { return arr.indexOf(obj) !== -1; } : function(arr, obj) { for(var i = -1, j = arr.length; ++i < j;) if(arr[i] === obj) return true; return false; }; 

Preferisco usare la funzione standard e lasciare questo tipo di micro-ottimizzazione per quando è davvero necessario. Ma se sei appassionato di micro-ottimizzazione, ho adattato i parametri di riferimento a cui roosterononacid si collegava nei commenti, per confrontare le ricerche negli array . Sono piuttosto rozzi però, un'indagine completa proverebbe gli array con tipi diversi, lunghezze diverse e oggetti che si trovano in luoghi diversi.

Se la matrice non è ordinata, non c’è davvero un modo migliore (a parte l’uso di indexOf, che credo equivale alla stessa cosa). Se l’array è ordinato, puoi fare una ricerca binaria, che funziona in questo modo:

  1. Scegli l’elemento centrale dell’array.
  2. L’elemento che stai cercando è più grande dell’elemento che hai scelto? Se è così, hai eliminato la metà inferiore dell’array. Se non lo è, hai eliminato la metà superiore.
  3. Seleziona l’elemento centrale della restante metà dell’array e continua come nel passaggio 2, eliminando le metà dell’array rimanente. Alla fine troverai il tuo elemento o non avrai più alcun array da esaminare.

La ricerca binaria viene eseguita in tempo proporzionale al logaritmo della lunghezza dell’array, quindi può essere molto più veloce rispetto a ogni singolo elemento.

supponendo che .indexOf() sia implementato

 Object.defineProperty( Array.prototype,'has', { value:function(o, flag){ if (flag === undefined) { return this.indexOf(o) !== -1; } else { // only for raw js object for(var v in this) { if( JSON.stringify(this[v]) === JSON.stringify(o)) return true; } return false; }, // writable:false, // enumerable:false }) 

!!! non rendere Array.prototype.has=function(){... perché aggiungerai un elemento enumerabile in ogni array e js è rotto.

 //use like [22 ,'a', {prop:'x'}].has(12) // false ["a","b"].has("a") // true [1,{a:1}].has({a:1},1) // true [1,{a:1}].has({a:1}) // false 

l’uso del secondo arg (flag) forza il confronto per valore invece che per riferimento

Dipende dal tuo scopo. Se si programma per il Web, evitare indexOf , non è supportato da Internet Explorer 6 (molti di essi sono ancora in uso!), O fare uso condizionale:

 if (yourArray.indexOf !== undefined) result = yourArray.indexOf(target); else result = customSlowerSearch(yourArray, target); 

indexOf è probabilmente codificato nel codice nativo, quindi è più veloce di qualsiasi cosa tu possa fare in JavaScript (eccetto ricerca binaria / dicotomia se l’array è appropriato). Nota: è una questione di gusti, ma farei un return false; alla fine della tua routine, per restituire un vero booleano …

Ecco alcune meta-conoscenze per te – se vuoi sapere cosa puoi fare con un array, controlla la documentazione – ecco la pagina Array per Mozilla

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array

Lì vedrai il riferimento a indexOf, aggiunto in Javascript 1.6

Un modo efficace per verificare se un object è un array in javascript è dettagliato qui:

Ecco due funzioni del framework xa.js che allego a un utils = {} ‘container’. Questi dovrebbero aiutarti a rilevare correttamente gli array.

 var utils = {}; /** * utils.isArray * * Best guess if object is an array. */ utils.isArray = function(obj) { // do an instanceof check first if (obj instanceof Array) { return true; } // then check for obvious falses if (typeof obj !== 'object') { return false; } if (utils.type(obj) === 'array') { return true; } return false; }; /** * utils.type * * Attempt to ascertain actual object type. */ utils.type = function(obj) { if (obj === null || typeof obj === 'undefined') { return String (obj); } return Object.prototype.toString.call(obj) .replace(/\[object ([a-zA-Z]+)\]/, '$1').toLowerCase(); }; 

Se poi vuoi verificare se un object si trova in un array, includerei anche questo codice:

 /** * Adding hasOwnProperty method if needed. */ if (typeof Object.prototype.hasOwnProperty !== 'function') { Object.prototype.hasOwnProperty = function (prop) { var type = utils.type(this); type = type.charAt(0).toUpperCase() + type.substr(1); return this[prop] !== undefined && this[prop] !== window[type].prototype[prop]; }; } 

E infine questa funzione in_array:

 function in_array (needle, haystack, strict) { var key; if (strict) { for (key in haystack) { if (!haystack.hasOwnProperty[key]) continue; if (haystack[key] === needle) { return true; } } } else { for (key in haystack) { if (!haystack.hasOwnProperty[key]) continue; if (haystack[key] == needle) { return true; } } } return false; }