¿La mejor manera de encontrar si un elemento está en una matriz de JavaScript? [duplicar]

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

  •  02-07-2019
  •  | 
  •  

Pregunta

    

Esta pregunta ya tiene una respuesta aquí:

         

¿Cuál es la mejor manera de encontrar si un objeto está en una matriz?

Esta es la mejor manera que conozco:

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
¿Fue útil?

Solución

A partir de ECMAScript 2016 puede usar < código> includes ()

arr.includes(obj);

Si desea admitir IE u otros navegadores antiguos:

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

EDITAR: Esto no funcionará en IE6, 7 u 8 sin embargo. La mejor solución es definirlo usted mismo si no está presente:

  1. Mozilla (ECMA-262) versión :

      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 versión de s:

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

Otros consejos

Si está utilizando jQuery:

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

Para obtener más información: http://api.jquery.com/jQuery.inArray/

Primero, implemente indexOf en JavaScript para los navegadores que aún no lo tienen. Por ejemplo, consulte extras de la matriz de Erik Arvidsson (también, el publicación de blog asociada ). Y luego puede usar indexOf sin preocuparse por el soporte del navegador. Aquí hay una versión ligeramente optimizada de su implementación de 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;
    };
}

Se ha cambiado para almacenar la longitud de modo que no sea necesario buscarlo en cada iteración. Pero la diferencia no es enorme. Una función menos general podría ser más rápida:

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

Prefiero usar la función estándar y dejar este tipo de microoptimización para cuando sea realmente necesario. Pero si estás interesado en la micro-optimización, adapté los puntos de referencia que roosterononacid vinculado en los comentarios, a búsqueda de referencia en matrices . Sin embargo, son bastante crudos, una investigación completa probaría matrices con diferentes tipos, diferentes longitudes y la búsqueda de objetos que ocurren en diferentes lugares.

Si la matriz no está clasificada, no hay una mejor manera (aparte de usar el índice de referencia mencionado anteriormente, que creo que equivale a lo mismo). Si la matriz está ordenada, puede hacer una búsqueda binaria, que funciona así:

  1. Selecciona el elemento central de la matriz.
  2. ¿El elemento que buscas es más grande que el elemento que elegiste? Si es así, has eliminado la mitad inferior de la matriz. Si no es así, has eliminado la mitad superior.
  3. Elija el elemento central de la mitad restante de la matriz y continúe como en el paso 2, eliminando las mitades de la matriz restante. Eventualmente encontrará su elemento o no le quedará ninguna matriz para mirar.

La búsqueda binaria se ejecuta en un tiempo proporcional al logaritmo de la longitud de la matriz, por lo que puede ser mucho más rápido que mirar cada elemento individual.

[] .has (obj)

asumiendo que .indexOf () está implementado

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

!!! no cree Array.prototype.has = function () {... porque agregará un elemento enumerable en cada matriz y js está roto.

//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

el uso de 2nd arg (flag) fuerza la comparación por valor en lugar de referencia

comparando objetos en bruto

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

Depende de tu propósito. Si programa para la Web, evite indexOf , no es compatible con Internet & nbsp; Explorer & nbsp; 6 (¡muchos de ellos aún se usan!), O haga uso condicional:

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

indexOf probablemente esté codificado en código nativo, por lo que es más rápido que cualquier cosa que pueda hacer en JavaScript (excepto la búsqueda binaria / dicotomía si la matriz es apropiada). Nota: es una cuestión de gusto, pero al final de su rutina, haría un return false; para devolver un verdadero Boolean ...

Aquí hay algo de meta-conocimiento para usted: si desea saber qué puede hacer con un Array, consulte la documentación: aquí está la página de Array para Mozilla

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

Allí verás la referencia a indexOf, agregada en Javascript 1.6

Una forma robusta de verificar si un objeto es una matriz en javascript se detalla aquí:

Aquí hay dos funciones del marco xa.js que adjunto a un utils = {} & # 8216; contenedor & # 8217 ;. Esto debería ayudarlo a detectar matrices correctamente.

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

Si luego quiere comprobar si un objeto está en una matriz, también incluiría este código:

/**
 * 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];
    };
}

Y finalmente esta función 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;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top