¿Cómo verifico si una matriz incluye un valor en JavaScript?

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

Esta es la única forma que conozco de hacerlo:

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

¿Existe una forma mejor y más concisa de lograr esto?

preguntado Oct 25 '08, 20:10

recién probado: su camino es en realidad el más rápido para todos los navegadores: jsperf.com/find-element-in-obj-vs-array/2 (aparte de guardar previamente a.length en una variable) mientras que el uso de indexOf (como en $ .inArray) es mucho más lento -

muchos han respondido que Array # indexOf es su mejor opción aquí. Pero si desea algo que se pueda convertir correctamente en booleano, use esto: ~[1,2,3].indexOf(4) devolverá 0 que se evaluará como falso, mientras que ~[1,2,3].indexOf(3) devolverá -3 que se evaluará como verdadero. -

~ no es lo que quieres usar para convertir a booleano, para eso necesitas !. Pero en este caso, desea verificar la igualdad con -1, por lo que la función podría terminarreturn [1,2,3].indexOf(3) === -1; ~ es un binario no, invertirá cada bit del valor individualmente. -

@Iordvlad [1,2,3].indexOf(4) realmente volver -1. Como señaló @mcfedr, ~ es la operador bit a bit, ver ES5 11.4.8. La cosa es que, dado que la representación binaria de -1 consta de solo 1, su complemento es 0, que se evalúa como falso. El complemento de cualquier otro número será distinto de cero, por lo tanto, verdadero. Entonces, ~ funciona bien y a menudo se usa junto con indexOf. -

El título es engañoso. Dónde está el [[1,2],[3,4]].includes([3,4]) ? -

30 Respuestas

Los navegadores modernos tienen Array#includes, que hace exactamente eso y es ampliamente apoyado por todos excepto IE:

console.log(['joe', 'jane', 'mary'].includes('jane')); //true

También puedes usar Array#indexOf, que es menos directo, pero no requiere polyfills para navegadores obsoletos.

console.log(['joe', 'jane', 'mary'].indexOf('jane') >= 0); //true


Muchos marcos también ofrecen métodos similares:

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

respondido 03 nov., 20:17

MooTools también tiene Array.contains que devuelve un booleano, que suena como la verdadera pregunta aquí. - Ryan Florencia

el prototipo también tiene Array.include que devuelve un booleano - user102008

Si está utilizando un buen navegador, puede usar array.indexOf(object) != -1 - Sam Soffes

Además, no use indexOf solo como condición, porque el primer elemento devolverá 0 y se evaluará como falso - más-

inArray es un nombre terrible para una función que devuelve el índice del elemento, y -1 si no existe. Esperaría que se devolviera un booleano. - Tim

Actualización de 2019: esta respuesta es de 2008 (¡11 años!) Y no es relevante para el uso moderno de JS. La mejora de rendimiento prometida se basó en un punto de referencia realizado en navegadores de esa época. Puede que no sea relevante para los contextos de ejecución de JS modernos. Si necesita una solución sencilla, busque otras respuestas. Si necesita el mejor rendimiento, realice una evaluación comparativa en los entornos de ejecución relevantes.

Como han dicho otros, la iteración a través de la matriz es probablemente la mejor manera, pero se ha demostrado que una decreciente while loop es la forma más rápida de iterar en JavaScript. Entonces, 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 puede extender el prototipo Array:

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

Y ahora simplemente puede usar lo siguiente:

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

Respondido 07 ago 19, 11:08

"Probado" es una palabra fuerte. Los motores JS mejoran constantemente y el tiempo de ejecución medido hace 3 años está terriblemente desactualizado. - orip

@ Damir - Estoy de acuerdo. Quizás cambie la muestra para usar indexOf si está disponible, solo para que las personas que copian y pegan este código a ciegas obtengan el mejor rendimiento posible. - orip

@cbmeeks sí, definitivamente se necesita cuidado. Probablemente fue un caso de hacer for (o in array) que no se debe hacer cuando se recorre la matriz en general ... - damir zekić

La mejor forma de hacerlo es comprobar si [1, 2, 3] .indexOf (1)> -1 - devin rhode

indexOf tal vez, pero es una "extensión JavaScript del estándar ECMA-262; como tal, puede que no esté 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 admiten indexOf) si quieres, como La búsqueda rápida de Google revela (por ejemplo, esta).

Respondido 12 ago 11, 00:08

de hecho, hay un ejemplo de la implementación de la extensión indexOf para navegadores que no la admiten en la página developer.mozilla.org a la que se vinculó. - lloyd cotten

en realidad, si agrega indexof al prototipo de Array para navegadores que no lo soportan (es decir, IE7), también intentarán recorrer esta función al recorrer los elementos de la matriz. desagradable. - CPILL

¿Es aplicable verificar el Objeto? no creo que funcione en el caso del objeto - himesh aadeshara

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 la indexOf, Que utiliza Comparación estricta de igualdad, includes compara el uso MismoValorCero algoritmo de igualdad. Eso significa que puede detectar si una matriz incluye un NaN:

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

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

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

Actualmente todavía es un borrador, pero puede ser polietileno para que funcione en todos los navegadores.

Respondido 08 Feb 16, 16:02

No es compatible con IE y Microsfot Edge (2015) (desarrollador.mozilla.org/en-US/docs/Web/JavaScript/Reference/…) - Adriano Resende

También relevante, el Tabla de compatibilidad ES7 (parece que Chrome lo admite ahora) - estilo

¿Es aplicable verificar el Objeto? no creo que funcione en el caso del objeto - himesh aadeshara

Las respuestas principales asumen tipos primitivos, pero si desea averiguar si una matriz contiene un objeto con algún rasgo, Array.prototype.some () es una solución elegante:

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

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

Lo bueno de esto es que la iteración se aborta una vez que se encuentra el elemento, por lo que se evitan los ciclos de iteración innecesarios.

Además, encaja muy bien en un if declaración ya que devuelve un booleano:

if (items.some(item => item.a === '3')) {
  // do something
}

* Como señaló Jamess en el comentario, en el momento de esta respuesta, septiembre de 2018, Array.prototype.some() es totalmente compatible: tabla de soporte de caniuse.com

Respondido 24 ago 20, 12:08

A partir de hoy, septiembre de 2018, Array.prototype.some () es totalmente compatible: tabla de soporte de caniuse.com - James

Trabajando en Node> = 8.10 para AWS Node.js Lambda, esto es genial. ¡Solución muy limpia y sencilla! 👍🏻 - Jordania

@jamess Puede que esté bien soportado, pero recuerda que Arrow functions en este ejemplo no están tan bien respaldados. Para obtener más detalles, consulte aquí: desarrollador.mozilla.org/en-US/docs/Web/JavaScript/Reference/… - Kamil Witkowski

¿Algún cortocircuito? ¿O itera toda la matriz incluso si encuentra un valor? - douglas gaskell

@DouglasGaskell aborta la iteración una vez encontrada (mencionada en la respuesta) - Michael

Digamos que ha definido una matriz así:

const array = [1, 2, 3, 4]

A continuación se muestran tres formas de comprobar si hay un 3 ahí. Todos regresan bien true or false.

Método de matriz nativa (desde ES2016) (tabla de compatibilidad)

array.includes(3) // true

Como método de matriz personalizado (anterior a ES2016)

// Prefixing the method with '_' to avoid name clashes
Object.defineProperty(Array.prototype, '_includes', { value: function (v) { return this.indexOf(v) !== -1 }})
array._includes(3) // true

Función simple

const includes = (a, v) => a.indexOf(v) !== -1
includes(array, 3) // true

respondido 13 nov., 19:17

Devuelve verdadero si "b" está en la matriz "a" ... No sé de qué otra manera explicarlo ... - william malo

Esta parte no la entiendo "!! ~". Y creo que esto no funcionará en IE8 porque IE8 no es compatible con indexOf () en el objeto Array. - svlada

"~" es un operador que pisos, invierte y resta 1 de un número. indexOf devuelve -1 si falla, por lo que "~" convierte -1 en "0". utilizando "!!" convierte números en boleanos (!! 0 === falso) - william malo

Genial, pero en serio por simplicidad y no solo a.indexOf (b)> - 1, ya que "> -1" .length === "!! ~" .length - user2039981

Yo llamaría poco profesional a la falta de conocimiento sobre los efectos de los operadores booleanos. Pero estoy de acuerdo con el valor del código legible, ciertamente lo envolvería en una función claramente etiquetada. Y eso es exactamente lo que hacen la mayoría de los principales marcos de JS. - okdewit

Aquí hay una Compatible con JavaScript 1.6 aplicació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;
        };
}

Respondido el 30 de enero de 19 a las 10:01

Esto se ve muy bien, pero un poco confuso: * ¿No son equivalentes las pruebas de las líneas 1 y 3? * ¿No sería mejor probar el prototipo y agregar la función a Array.prototype si fuera necesario? - Avi lino

No son equivalentes. [].indexOf es una abreviatura de Array.prototype.indexOf. Los programadores de Javascript defensivos paranoicos evitamos extender los prototipos nativos a toda costa. - mar Örlygsson

No es [].indexOf creando una nueva matriz y luego accediendo indexOf, mientras que Array.prototype.indexOf solo accede directamente al prototipo? - alex

@alex sí [].indexOf === Array.prototype.indexOf (pruébalo en FireBug), pero a la inversa [].indexOf !== Array.indexOf. - mar Örlygsson

Uso:

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

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

Respondido el 07 de enero de 17 a las 11:01

x ? true : false suele ser redundante. Es aquí. - Ry- ♦

@minitech ¿Por qué dices que es redundante? - matias canepa

array.indexOf(search) >= 0 ya es un booleano. Sólo return array.indexOf(search) >= 0. - Ry- ♦

@minitech bueno gracias! En realidad, no sabía que una construcción así podría devolverse. HASTA algo nuevo. - matias canepa

Literalmente, se puede devolver cualquier construcción en javascript: BT

Extendiendo el JavaScript Array object es una muy mala idea porque introduces nuevas propiedades (tus métodos personalizados) en for-in bucles que pueden romper los scripts existentes. Hace unos años los autores de la Prototipo library tuvo que rediseñar la implementación de su biblioteca para eliminar este tipo de cosas.

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

Respondido 12 ago 11, 00:08

Estoy en desacuerdo. Los bucles for-in no deben usarse para matrices precisamente por esta razón. El uso de bucles for-in se romperá al usar una de las bibliotecas js populares: Tomas

¿Se consideraría esto un parche de mono? lol A algunas personas les gusta eso. - cbmeeks

Un trazador de líneas:

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

Respondido el 07 de enero de 17 a las 11:01

array.filter(e=>e==x).length > 0 es equivalente a array.some(e=>e==x) pero some es más eficiente - Apolo

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

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

contestado el 06 de mayo de 18 a las 19:05

Aunque obviamente esto es útil para muchos, hubiera sido mejor si se hubiera agregado un fragmento de código. - Pie 'Oh' Pah

Rendimiento

Hoy 2020.01.07 realizo pruebas en MacOs HighSierra 10.13.6 en Chrome v78.0.0, Safari v13.0.4 y Firefox v71.0.0 para 15 soluciones elegidas. Conclusiones

  • soluciones basadas en JSON, Set y sorprendentemente find (K, N, O) son los más lentos en todos los navegadores
  • el es6 includes (F) es rápido solo en Chrome
  • las soluciones basadas en for (C, D) y indexOf (G, H) son bastante rápidos en todos los navegadores en arreglos pequeños y grandes, por lo que probablemente sean la mejor opción para una solución eficiente
  • las soluciones donde el índice disminuye durante el ciclo, (B) es más lento probablemente porque la forma de La caché de la CPU funciona.
  • También ejecuto una prueba para una matriz grande cuando el elemento buscado estaba en la posición 66% de la longitud de la matriz y las soluciones se basan en for (C, D, E) da resultados similares (~ 630 operaciones / seg, pero la E en safari y firefox fue un 10-20% más lenta que C y D)

Resultados

enter image description here

Detalles

Realizo 2 casos de prueba: para matriz con 10 elementos y matriz con 1 millón de elementos. En ambos casos, colocamos el elemento buscado en el medio de la matriz.

let log = (name,f) => console.log(`${name}: 3-${f(arr,'s10')}  's7'-${f(arr,'s7')}  6-${f(arr,6)} 's3'-${f(arr,'s3')}`)

let arr = [1,2,3,4,5,'s6','s7','s8','s9','s10'];
//arr = new Array(1000000).fill(123); arr[500000]=7;

function A(a, val) {
    var i = -1;
    var n = a.length;
    while (i++<n) {
       if (a[i] === val) {
           return true;
       }
    }
    return false;
}

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

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

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

function E(a, val){  
  var n = a.length-1;
  var t = n/2;
  for (var i = 0; i <= t; i++) {
        if (a[i] === val || a[n-i] === val) return true;
  }
  return false;
}

function F(a,val) {
	return a.includes(val);
}

function G(a,val) {
	return a.indexOf(val)>=0;
}

function H(a,val) {
	return !!~a.indexOf(val);
}

function I(a, val) {
  return a.findIndex(x=> x==val)>=0;
}

function J(a,val) {
	return a.some(x=> x===val);
}

function K(a, val) {
  const s = JSON.stringify(val);
  return a.some(x => JSON.stringify(x) === s);
}

function L(a,val) {
	return !a.every(x=> x!==val);
}

function M(a, val) {
  return !!a.find(x=> x==val);
}

function N(a,val) {
	return a.filter(x=>x===val).length > 0;
}

function O(a, val) {
  return new Set(a).has(val);
}

log('A',A);
log('B',B);
log('C',C);
log('D',D);
log('E',E);
log('F',F);
log('G',G);
log('H',H);
log('I',I);
log('J',J);
log('K',K);
log('L',L);
log('M',M);
log('N',N);
log('O',O);
This shippet only presents functions used in performance tests - it not perform tests itself!

Matriz pequeña - 10 elementos

Puedes realizar pruebas en tu máquina AQUÍ

enter image description here

Matriz grande - 1.000.000 elementos

Puedes realizar pruebas en tu máquina AQUÍ

enter image description here

respondido 11 mar '20, 16:03

Yo uso lo siguiente:

Array.prototype.contains = function (v) {
    return this.indexOf(v) > -1;
}

var a = [ 'foo', 'bar' ];

a.contains('foo'); // true
a.contains('fox'); // false

Respondido el 15 de junio de 14 a las 02:06

function contains(a, obj) {
    return a.some(function(element){return element == obj;})
}

Array.prototype.some () se agregó al estándar ECMA-262 en la quinta edición

Respondido el 12 de Septiembre de 14 a las 17:09

si usa es6, entonces se puede acortar como contains = (a, obj) => a.some((element) => element === obj)) - diEcho

Incluso IE9 tiene soporte para Array.prototype.some () a partir de ECMAScript 5. - Suncat2000

Un bidireccional con suerte más rápido indexOf / lastIndexOf alternativa

2015

Mientras que el nuevo método incluye es muy bueno, el soporte es básicamente cero por ahora.

Hace mucho tiempo que estaba pensando en la forma de reemplazar las funciones lentas indexOf / lastIndexOf.

Ya se ha encontrado una forma de rendimiento, mirando las respuestas principales. De los que elegí el contains función publicada por @Damir Zekic, que debería ser la más rápida. Pero también establece que los puntos de referencia son de 2008 y, por lo tanto, están desactualizados.

Yo tambien prefiero while encima for, pero no por una razón específica, terminé de escribir la función con un bucle for. También se puede hacer con un while --.

Tenía curiosidad por saber si la iteración era mucho más lenta si verifico ambos lados de la matriz mientras lo hacía. Aparentemente no, por lo que esta función es aproximadamente dos veces más rápida que las más votadas. Obviamente también es más rápido que el nativo. Esto en un entorno del mundo real, donde nunca se sabe si el valor que está buscando está al principio o al final de la matriz.

Cuando sabe que acaba de enviar una matriz con un valor, usar lastIndexOf sigue siendo probablemente la mejor solución, pero si tiene que viajar a través de matrices grandes y el resultado podría estar en todas partes, esta podría ser una solución sólida para hacer las cosas más rápido.

Bidireccional indexOf / 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');

Prueba de rendimiento

http://jsperf.com/bidirectionalindexof

Como prueba, creé una matriz con 100k entradas.

Tres consultas: al principio, en el medio y al final de la matriz.

Espero que también encuentres esto interesante y pruebes el rendimiento.

Nota: Como puede ver, modifiqué ligeramente el contains función para reflejar la salida indexOf y lastIndexOf (así que básicamente true con el index y false con -1). Eso no debería dañarlo.

La variante del prototipo de matriz

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 función también se puede modificar fácilmente para devolver verdadero o falso o incluso el objeto, la cadena o lo que sea.

Y aquí está el 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');

¿Cómo es esto posible?

Creo que el cálculo simple para obtener el índice reflejado en una matriz es tan simple que es dos veces más rápido que hacer una iteración de bucle real.

Aquí hay un ejemplo complejo que hace tres comprobaciones por iteración, pero esto solo es posible con un cálculo más largo que provoca la ralentización del código.

http://jsperf.com/bidirectionalindexof/2

Respondido el 07 de enero de 17 a las 11:01

Si está usando JavaScript 1.6 o posterior (Firefox 1.5 o posterior) puede usar Array.indexOf. De lo contrario, creo que terminará con algo similar a su código original.

Respondido 25 Oct 08, 23:10

function inArray(elem,array)
{
    var len = array.length;
    for(var i = 0 ; i < len;i++)
    {
        if(array[i] == elem){return i;}
    }
    return -1;
} 

Devuelve el índice de la matriz si se encuentra, o -1 si no se encuentra

Respondido el 06 de Septiembre de 14 a las 17:09

Si está comprobando repetidamente la existencia de un objeto en una matriz, tal vez debería investigar

  1. Mantener la matriz ordenada en todo momento haciendo tipo de inserción en su matriz (coloque nuevos objetos en el lugar correcto)
  2. Realice la actualización de objetos como operación de inserción eliminar + ordenada y
  3. Utilizar búsqueda binaria buscar en tu contains(a, obj).

Respondido 05 Feb 11, 18:02

O, si es posible, deje de usar una matriz por completo y, en su lugar, use un objeto como diccionario, como han sugerido MattMcKnight y ninjagecko. - joeytwiddle

Usamos este fragmento (funciona con objetos, matrices, cadenas):

/*
 * @function
 * @name Object.prototype.inArray
 * @description Extend Object prototype within inArray function
 *
 * @param {mix}    needle       - Search-able needle
 * @param {bool}   searchInKey  - Search needle in keys?
 *
 */
Object.defineProperty(Object.prototype, 'inArray',{
    value: function(needle, searchInKey){

        var object = this;

        if( Object.prototype.toString.call(needle) === '[object Object]' || 
            Object.prototype.toString.call(needle) === '[object Array]'){
            needle = JSON.stringify(needle);
        }

        return Object.keys(object).some(function(key){

            var value = object[key];

            if( Object.prototype.toString.call(value) === '[object Object]' || 
                Object.prototype.toString.call(value) === '[object Array]'){
                value = JSON.stringify(value);
            }

            if(searchInKey){
                if(value === needle || key === needle){
                return true;
                }
            }else{
                if(value === needle){
                    return true;
                }
            }
        });
    },
    writable: true,
    configurable: true,
    enumerable: false
});

Uso:

var a = {one: "first", two: "second", foo: {three: "third"}};
a.inArray("first");          //true
a.inArray("foo");            //false
a.inArray("foo", true);      //true - search by keys
a.inArray({three: "third"}); //true

var b = ["one", "two", "three", "four", {foo: 'val'}];
b.inArray("one");         //true
b.inArray('foo');         //false
b.inArray({foo: 'val'})   //true
b.inArray("{foo: 'val'}") //false

var c = "String";
c.inArray("S");        //true
c.inArray("s");        //false
c.inArray("2", true);  //true
c.inArray("20", true); //false

Respondido el 10 de Septiembre de 14 a las 13:09

Solución que funciona en todos los navegadores modernos:

function contains(arr, obj) {
  const stringifiedObj = JSON.stringify(obj); // Cache our object to not call `JSON.stringify` on every iteration
  return arr.some(item => JSON.stringify(item) === stringifiedObj);
}

Uso:

contains([{a: 1}, {a: 2}], {a: 1}); // true

Solución IE6 +:

function contains(arr, obj) {
  var stringifiedObj = JSON.stringify(obj)
  return arr.some(function (item) {
    return JSON.stringify(item) === stringifiedObj;
  });
}

// .some polyfill, not needed for IE9+
if (!('some' in Array.prototype)) {
  Array.prototype.some = function (tester, that /*opt*/) {
    for (var i = 0, n = this.length; i < n; i++) {
      if (i in this && tester.call(that, this[i], i, this)) return true;
    } return false;
  };
}

Uso:

contains([{a: 1}, {a: 2}], {a: 1}); // true

Por que usar JSON.stringify?

Array.indexOf y Array.includes (así como la mayoría de las respuestas aquí) solo compare por referencia y no por valor.

[{a: 1}, {a: 2}].includes({a: 1});
// false, because {a: 1} is a new object

Bono

Una sola línea ES6 no optimizada:

[{a: 1}, {a: 2}].some(item => JSON.stringify(item) === JSON.stringify({a: 1));
// true

Nota: Comparar objetos por valor funcionará mejor si las claves están en el mismo orden, por lo que para estar seguro, puede ordenar las claves primero con un paquete como este: https://www.npmjs.com/package/sort-keys


Actualizado el contains función con una optimización de rendimiento. Gracias itinancia por señalarlo.

Respondido 05 Jul 17, 00:07

Este fragmento de código en particular puede funcionar en IE6 (no se ha probado), pero IE no admitió ES5 hasta IE9. - mark Reed

Por razones de rendimiento, debe evitar las cadenas. Al menos debe evitar utilizar JSON. Stringificar el "obj" en cada bucle porque es caro y ralentizará su aplicación. Por lo tanto, debe capturarlo antes del bucle for en una variable temporal: itinancia

@itinance buen punto. Actualizado el includes Funciona con tu sugerencia. Ejecuté jsperf con mi función. Es aproximadamente 5 veces más lento de lo que incluye lodash. Aunque lodash no se compara por valor y no puede encontrar {a: 1} in [{a: 1}]. No sé si alguna biblioteca lo hace. Pero tengo curiosidad por saber si hay alguna forma más eficaz y no increíblemente compleja de hacerlo. - Igor Barbashin

Nota tardía: esto no funciona con, digamos, contains([{ a: 1, b: 2 }], { b: 2, a: 1 }) porque los objetos en cadena mantienen el orden de las propiedades. - Mono hereje

@HereticMonkey, cierto. Por eso agregué el sort-keys nota en la parte inferior - Igor Barbashin

Usa lodash's algo función.

Es conciso, preciso y tiene un excelente soporte multiplataforma.

La respuesta aceptada ni siquiera cumple con los requisitos.

Requisitos: Recomendar la forma más concisa y eficiente de averiguar si una matriz de JavaScript contiene un objeto.

Respuesta aceptada:

$.inArray({'b': 2}, [{'a': 1}, {'b': 2}])
> -1

Mi recomendación:

_.some([{'a': 1}, {'b': 2}], {'b': 2})
> true

Notas

$ .inArray funciona bien para determinar si un escalar el valor existe en una matriz de escalares ...

$.inArray(2, [1,2])
> 1

... pero la pregunta pide claramente una forma eficiente de determinar si un objeto está contenido en una matriz.

Para manejar escalares y objetos, puede hacer esto:

(_.isObject(item)) ? _.some(ary, item) : (_.indexOf(ary, item) > -1)

Respondido 21 Oct 15, 12:10

ECMAScript 6 tiene una elegante propuesta para encontrar.

El método de búsqueda ejecuta la función de devolución de llamada una vez para cada elemento presente en la matriz hasta que encuentra uno donde la devolución de llamada devuelve un valor verdadero. Si se encuentra un elemento de este tipo, find devuelve inmediatamente el valor de ese elemento. De lo contrario, busque devoluciones indefinidas. la devolución de llamada se invoca solo para los índices de la matriz que tienen valores asignados; no se invoca para índices que se han eliminado o a los que nunca se les han asignado valores.

Aquí está la Documentación MDN en eso.

La funcionalidad de búsqueda funciona así.

function isPrime(element, index, array) {
    var start = 2;
    while (start <= Math.sqrt(element)) {
        if (element % start++ < 1) return false;
    }
    return (element > 1);
}

console.log( [4, 6, 8, 12].find(isPrime) ); // Undefined, not found
console.log( [4, 5, 8, 12].find(isPrime) ); // 5

Puede usar esto en ECMAScript 5 y a continuación por definiendo la función.

if (!Array.prototype.find) {
  Object.defineProperty(Array.prototype, 'find', {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function(predicate) {
      if (this == null) {
        throw new TypeError('Array.prototype.find called on null or undefined');
      }
      if (typeof predicate !== 'function') {
        throw new TypeError('predicate must be a function');
      }
      var list = Object(this);
      var length = list.length >>> 0;
      var thisArg = arguments[1];
      var value;

      for (var i = 0; i < length; i++) {
        if (i in list) {
          value = list[i];
          if (predicate.call(thisArg, value, i, list)) {
            return value;
          }
        }
      }
      return undefined;
    }
  });
}

Respondido el 07 de enero de 17 a las 11:01

Aunque la array.indexOf(x)!=-1 es la forma más concisa de hacer esto (y ha sido compatible con navegadores que no son de Internet Explorer durante más de una década ...), no es O (1), sino O (N), lo cual es terrible. Si su matriz no cambiará, puede convertir su matriz en una tabla hash, luego haga table[x]!==undefined or ===undefined:

Array.prototype.toTable = function() {
    var t = {};
    this.forEach(function(x){t[x]=true});
    return t;
}

Demostración:

var toRemove = [2,4].toTable();
[1,2,3,4,5].filter(function(x){return toRemove[x]===undefined})

(Desafortunadamente, aunque puede crear un Array.prototype.contains para "congelar" una matriz y almacenar una tabla hash en this._cache en dos líneas, esto daría resultados incorrectos si elige editar su matriz más tarde. JavaScript no tiene suficientes ganchos para le permite mantener este estado, a diferencia de Python, por ejemplo).

Respondido el 07 de enero de 17 a las 11:01

Uno puede usar Kit que tiene el método "has ()":

function contains(arr, obj) {
      var proxy = new Set(arr);
      if (proxy.has(obj))
        return true;
      else
        return false;
    }

    var arr = ['Happy', 'New', 'Year'];
    console.log(contains(arr, 'Happy'));

Respondido el 24 de enero de 20 a las 12:01

Creo que el return proxy.has(obj) es mucho más limpio que dos líneas con la declaración if-else aquí - Maciej Bukowski

function contains(arr, obj) { return new Set(arr).has(obj); } - Frijol gordon

Uso:

var myArray = ['yellow', 'orange', 'red'] ;

alert(!!~myArray.indexOf('red')); //true

Demo

Para saber exactamente lo que tilde ~ hacer en este punto, consulte esta pregunta ¿Qué hace una tilde cuando precede a una expresión?.

contestado el 23 de mayo de 17 a las 13:05

Esto ya fue publicado hace año y medio no es necesario repetirlo. - Shadow Wizard está vacunando

De hecho, no se ha publicado. No como una respuesta, sino como un comentario a una respuesta, e incluso entonces no es claro ni conciso. Gracias por publicarlo, Mina Gabriel. - T.CK

OK, puedes simplemente optimiza tu código para obtener el resultado!

Hay muchas formas de hacer esto que son más limpias y mejores, pero solo quería obtener tu patrón y aplicarlo usando JSON.stringify, simplemente haz algo como esto en tu caso:

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

Respondido 06 Feb 19, 14:02

Nota tardía: esto no funciona con, digamos, contains([{ a: 1, b: 2 }], { b: 2, a: 1 }) porque los objetos en cadena mantienen el orden de las propiedades. - Mono hereje

Una solución simple para este requisito es utilizar find()

Si tiene una variedad de objetos como a continuación,

var users = [{id: "101", name: "Choose one..."},
{id: "102", name: "shilpa"},
{id: "103", name: "anita"},
{id: "104", name: "admin"},
{id: "105", name: "user"}];

Luego puede verificar si el objeto con su valor ya está presente o no

let data = users.find(object => object['id'] === '104');

si los datos son nulos, entonces no hay administrador, de lo contrario, devolverá el objeto existente como se muestra a continuación.

{id: "104", name: "admin"}

Luego, puede encontrar el índice de ese objeto en la matriz y reemplazar el objeto usando el siguiente código.

let indexToUpdate = users.indexOf(data);
let newObject = {id: "104", name: "customer"};
users[indexToUpdate] = newObject;//your new object
console.log(users);

obtendrás valor como a continuación

[{id: "101", name: "Choose one..."},
{id: "102", name: "shilpa"},
{id: "103", name: "anita"},
{id: "104", name: "customer"},
{id: "105", name: "user"}];

Espero que esto ayude a cualquiera.

Respondido 11 Oct 19, 18:10

De ninguna manera el mejor, pero me estaba volviendo creativo y agregando al repertorio.

No use esto

Object.defineProperty(Array.prototype, 'exists', {
  value: function(element, index) {

    var index = index || 0

    return index === this.length ? -1 : this[index] === element ? index : this.exists(element, ++index)
  }
})


// Outputs 1
console.log(['one', 'two'].exists('two'));

// Outputs -1
console.log(['one', 'two'].exists('three'));

console.log(['one', 'two', 'three', 'four'].exists('four'));

Respondido el 20 de junio de 20 a las 10:06

¿Qué deberías usar si no es esto? - bryc

@bryc tal vez sea la solución aceptada, u otra solución de aquí. Si no te importa mucho el rendimiento, puedes usar esto: cuadrado

Me sorprende que esta pregunta todavía no tenga la última sintaxis agregada, agregando mis 2 centavos.

Digamos que tenemos una matriz de Objetos arrObj y queremos buscar obj en ella.

matriz.prototipo.índice de -> (devuelve índice o -1) se usa generalmente para encontrar el índice de un elemento en una matriz. Esto también se puede usar para buscar objetos, pero solo funciona si está pasando una referencia al mismo objeto.

let obj = { name: 'Sumer', age: 36 };
let arrObj = [obj, { name: 'Kishor', age: 46 }, { name: 'Rupen', age: 26 }];


console.log(arrObj.indexOf(obj));// 0
console.log(arrObj.indexOf({ name: 'Sumer', age: 36 })); //-1

console.log([1, 3, 5, 2].indexOf(2)); //3

matriz.prototipo.incluye -> (devuelve verdadero or false)

console.log(arrObj.includes(obj));  //true
console.log(arrObj.includes({ name: 'Sumer', age: 36 })); //false

console.log([1, 3, 5, 2].includes(2)); //true

matriz.prototipo.encontrar -> (recibe devolución de llamada, regresa primero valor / objeto que devuelve verdadero en CB).

console.log(arrObj.find(e => e.age > 40));  //{ name: 'Kishor', age: 46 }
console.log(arrObj.find(e => e.age > 40)); //{ name: 'Kishor', age: 46 }

console.log([1, 3, 5, 2].find(e => e > 2)); //3

matriz.prototipo.buscarÍndice -> (recibe devolución de llamada, devuelve índice del primer valor / objeto que devuelve verdadero en CB).

console.log(arrObj.findIndex(e => e.age > 40));  //1
console.log(arrObj.findIndex(e => e.age > 40)); //1

console.log([1, 3, 5, 2].findIndex(e => e > 2)); //1

Dado que find y findIndex toman una devolución de llamada, podemos recuperar cualquier objeto (incluso si no tenemos la referencia) de la matriz estableciendo creativamente la condición verdadera.

Respondido 07 Abr '19, 14:04

    function countArray(originalArray) {
     
    	var compressed = [];
    	// make a copy of the input array
    	var copyArray = originalArray.slice(0);
     
    	// first loop goes over every element
    	for (var i = 0; i < originalArray.length; i++) {
     
    		var count = 0;	
    		// loop over every element in the copy and see if it's the same
    		for (var w = 0; w < copyArray.length; w++) {
    			if (originalArray[i] == copyArray[w]) {
    				// increase amount of times duplicate is found
    				count++;
    				// sets item to undefined
    				delete copyArray[w];
    			}
    		}
     
    		if (count > 0) {
    			var a = new Object();
    			a.value = originalArray[i];
    			a.count = count;
    			compressed.push(a);
    		}
    	}
     
    	return compressed;
    };
    
    // It should go something like this:
    
    var testArray = new Array("dog", "dog", "cat", "buffalo", "wolf", "cat", "tiger", "cat");
    var newArray = countArray(testArray);
    console.log(newArray);

Respondido el 24 de enero de 20 a las 12:01

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.