Pregunta ¿Cómo puedo verificar si una matriz incluye un objeto en JavaScript?


¿Cuál es la forma más concisa y eficiente de averiguar si una matriz de JavaScript contiene un objeto?

Esta es la única forma en que sé hacerlo:

function contains(a, obj) {
    for (var i = 0; i < a.length; i++) {
        if (a[i] === obj) {
            return true;
        }
    }
    return false;
}

¿Hay una forma mejor y más concisa para lograr esto?

Esto está muy relacionado con la pregunta de desbordamiento de pila ¿La mejor forma de encontrar un artículo en una matriz de JavaScript? que aborda la búsqueda de objetos en una matriz usando indexOf.


3217
2017-10-25 22:14


origen


Respuestas:


Los navegadores actuales tienen Array#includes, que no exactamente ese, es ampliamente compatibley tiene un polyfill para navegadores más antiguos.

> ['joe', 'jane', 'mary'].includes('jane');
true 

También puedes usar Array#indexOf, que es menos directo, pero no requiere Polyfills para buscadores desactualizados.

jQuery ofrece $.inArray, que es funcionalmente equivalente a Array#indexOf.

underscore.js, una biblioteca de utilidades de JavaScript, ofertas _.contains(list, value), alias _.include(list, value), ambos usan índice de internamente si pasó una matriz de JavaScript.

Algunos otros marcos ofrecen métodos similares:

Observe que algunos marcos implementan esto como una función, mientras que otros agregan la función al prototipo de matriz.


3644
2017-10-25 23:10



Actualización: Como @orip menciona en los comentarios, el punto de referencia vinculado se realizó en 2008, por lo que los resultados pueden no ser relevantes para los navegadores modernos. Sin embargo, probablemente necesite esto para admitir navegadores no modernos de todos modos y probablemente no se hayan actualizado desde entonces. Siempre prueba por ti mismo.

Como han dicho otros, la iteración a través de la matriz es probablemente la mejor, pero se ha demostrado que una disminución while loop es la forma más rápida de iterar en JavaScript. Por lo tanto, es posible que desee reescribir su código de la siguiente manera:

function contains(a, obj) {
    var i = a.length;
    while (i--) {
       if (a[i] === obj) {
           return true;
       }
    }
    return false;
}

Por supuesto, también puedes extender el prototipo de Array:

Array.prototype.contains = function(obj) {
    var i = this.length;
    while (i--) {
        if (this[i] === obj) {
            return true;
        }
    }
    return false;
}

Y ahora puedes simplemente usar lo siguiente:

alert([1, 2, 3].contains(2)); // => true
alert([1, 2, 3].contains('2')); // => false

357
2017-10-25 22:49



indexOf tal vez, pero es una "extensión de JavaScript para el estándar ECMA-262; como tal, puede no estar presente en otras implementaciones del estándar".

Ejemplo:

[1, 2, 3].indexOf(1) => 0
["foo", "bar", "baz"].indexOf("bar") => 1
[1, 2, 3].indexOf(4) => -1

AFAICS Microsoft lo hace no ofrecer algún tipo de alternativa a esto, pero puede agregar una funcionalidad similar a las matrices en Internet Explorer (y otros navegadores que no son compatibles) indexOf) si lo desea, como la búsqueda rápida de Google revela (por ejemplo, éste)


156
2018-01-01 01:40



ECMAScript 7 presenta Array.prototype.includes.

Se puede usar así:

[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false

También acepta un segundo argumento opcional fromIndex:

[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true

diferente a indexOf, que usa Estricta comparación de igualdad, includes compara el uso SameValueZero algoritmo de igualdad. Eso significa que puede detectar si una matriz incluye una NaN:

[1, 2, NaN].includes(NaN); // true

También a diferencia indexOf, includes no omite los índices que faltan:

new Array(5).includes(undefined); // true

Actualmente sigue siendo un borrador, pero puede ser polyfilledpara que funcione en todos los navegadores.


128
2018-03-24 04:59



b es el valor, y a es la matriz Vuelve true o false:

function(a, b) {
    return a.indexOf(b) != -1
}

96
2017-10-27 00:38



Aquí está un JavaScript 1.6 compatible implementación de Array.indexOf:

if (!Array.indexOf)
{
  Array.indexOf = [].indexOf ?
      function (arr, obj, from) { return arr.indexOf(obj, from); }:
      function (arr, obj, from) { // (for IE6)
        var l = arr.length,
            i = from ? parseInt( (1*from) + (from<0 ? l:0), 10) : 0;
        i = i<0 ? 0 : i;
        for (; i<l; i++) {
          if (i in arr  &&  arr[i] === obj) { return i; }
        }
        return -1;
      };
}

65
2017-09-13 17:32



Utilizar:

function isInArray(array, search)
{
    return array.indexOf(search) >= 0;
}

// Usage
if(isInArray(my_array, "my_value"))
{
    //...
}

46
2017-08-27 16:45



Extendiendo el JavaScript Array objeto es una muy mala idea porque introduce nuevas propiedades (sus métodos personalizados) en for-in bucles que pueden romper las secuencias de comandos existentes. Hace algunos años, los autores del Prototipo la biblioteca tuvo que rediseñar la implementación de su biblioteca para eliminar solo este tipo de cosas.

Si no necesita preocuparse por la compatibilidad con otros JavaScript que se ejecutan en su página, consígalo, de lo contrario, recomendaría la solución de función independiente más incómoda, pero más segura.


38
2017-07-18 14:36



Puedes usar Array.prototype.some ()

const items = [ {a: '1'}, {a: '2'}, {a: '3'} ]

items.some(item => item.a === '3')  // returns true
items.some(item => item.a === '4')  // returns false

Al revés de esto, la iteración se cancela una vez que se encuentra el elemento, por lo que se guardan los ciclos de iteración innecesarios.

Una cosa a tener en cuenta es que some() no está presente en todas las versiones js: (desde el sitio web)

algunos se agregaron al estándar ECMA-262 en la quinta edición; como tal   puede no estar presente en todas las implementaciones del estándar

Puedes usarlo en Node.js sin ningún problema. Si necesita admitir todos los navegadores, existe este relleno policristalino (del mismo enlace):

if (!Array.prototype.some)
{
  Array.prototype.some = function(fun /*, thisArg */)
  {
    'use strict';

    if (this === void 0 || this === null)
      throw new TypeError();

    var t = Object(this);
    var len = t.length >>> 0;
    if (typeof fun !== 'function')
      throw new TypeError();

    var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
    for (var i = 0; i < len; i++)
    {
      if (i in t && fun.call(thisArg, t[i], i, t))
        return true;
    }

    return false;
  };
}

33
2018-01-07 12:49



Un trazador de líneas:

function contains(arr, x) {
    return arr.filter(function(elem) { return elem == x }).length > 0;
}

21
2017-12-23 15:59



Pensando por un segundo, si está haciendo esta llamada muchas veces, es mucho más eficiente de usar una matriz asociativa un Mapa para hacer búsquedas utilizando una función hash.

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


21
2018-06-15 01:15