Il modo migliore per scoprire se un elemento si trova in un array JavaScript? [duplicare]

StackOverflow https://stackoverflow.com/questions/143847

  •  02-07-2019
  •  | 
  •  

Domanda

    

Questa domanda ha già una risposta qui:

         

Qual è il modo migliore per trovare un oggetto 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
È stato utile?

Soluzione

A partire da ECMAScript 2016 è possibile utilizzare < code> include ()

arr.includes(obj);

Se desideri supportare IE o altri browser meno recenti:

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

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

  1. Mozilla's (ECMA-262) versione :

      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. 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. roosteronacid versione di:

    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);
      }
    );
    

Altri suggerimenti

Se si utilizza jQuery:

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

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

Innanzitutto, implementa indexOf in JavaScript per i browser che non lo possiedono già. Ad esempio, vedi Gli extra di array di Erik Arvidsson (anche, post di 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;
    };
}

È stato modificato per memorizzare la lunghezza in modo che non sia necessario cercarlo ad 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 è veramente necessario. Ma se sei appassionato di micro-ottimizzazione, ho adattato i benchmarks che roosterononacid collegato nei commenti, a ricerca benchmark negli array . Sono piuttosto rozzi, però, un'indagine completa testerebbe array con tipi diversi, lunghezze diverse e trova oggetti che si verificano in luoghi diversi.

Se l'array non è ordinato, non c'è davvero un modo migliore (oltre all'utilizzo dell'indiceOf di cui sopra, che penso equivalga alla stessa cosa). Se l'array è ordinato, puoi fare una ricerca binaria, che funziona così:

  1. Seleziona l'elemento centrale dell'array.
  2. L'elemento che stai cercando è più grande dell'elemento che hai scelto? In tal caso, hai eliminato la metà inferiore dell'array. In caso contrario, hai eliminato la metà superiore.
  3. Scegli l'elemento centrale della metà rimanente dell'array e continua come nel passaggio 2, eliminando le metà dell'array rimanente. Alla fine troverai il tuo elemento o non avrai più un array da guardare.

La ricerca binaria viene eseguita in un tempo proporzionale al logaritmo della lunghezza dell'array, quindi può essere molto più veloce che guardare ogni singolo elemento.

[] .has (obj)

presupponendo 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 creare 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 di 2nd arg (flag) forza il confronto per valore anziché per riferimento

confronto di oggetti grezzi

[o1].has(o2,true) // true if every level value is same

Dipende dal tuo scopo. Se programmi per il Web, evita indexOf , non è supportato da Internet & nbsp; Explorer & nbsp; 6 (molti di questi sono ancora usati!), O fai un uso condizionale:

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

indexOf è probabilmente codificato in codice nativo, quindi è più veloce di qualsiasi cosa tu possa fare in JavaScript (tranne la 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 -USA / docs / JavaScript / Reference / Global_Objects / Array

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

Un modo affidabile per verificare se un oggetto è un array in javascript è dettagliato qui:

Ecco due funzioni del xa.js che allego a un utils = {} & # 8216; container & # 8217 ;. Ciò dovrebbe 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 si desidera quindi verificare se un oggetto 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;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top