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


4000

¿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 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 manera mejor y más concisa de lograr esto?

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


49
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 una longitud en una variable) mientras usa indexOf (como en $ .inArray) es mucho más lento
Jörn Berkefeld

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

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

14
@Iordvlad en [1,2,3].indexOf(4)realidad devolverá -1 . Como señaló @mcfedr, ~es el operador bit-NOT , ver ES5 11.4.8. La cosa es que, dado que la representación binaria de -1consta 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. Por lo tanto, ~funciona bien y a menudo se usa junto con indexOf.
mknecht

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

Respuestas:


4381

Los navegadores modernos tienen Array#includes, lo que hace exactamente eso y es ampliamente compatible con todos, excepto IE:

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

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


Muchos marcos también 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.


42
MooTools también tiene Array.contains que devuelve un valor booleano, que aquí parece ser la pregunta real.
Ryan Florence

22
también tiene Array.includeun prototipo que devuelve un valor booleano
user102008

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

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

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

434

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 los navegadores de la época. Puede que no sea relevante para los contextos modernos de ejecución de JS. Si necesita una solución fácil, busque otras respuestas. Si necesita el mejor rendimiento, hágalo una referencia en los entornos de ejecución relevantes.

Como otros han dicho, la iteración a través de la matriz es probablemente la mejor manera, pero se ha demostrado que un whileciclo decreciente es la forma más rápida de iterar en JavaScript. Por lo tanto, es posible que desee volver a escribir 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 de matriz:

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


22
"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

2
@Damir: estoy de acuerdo. Quizás cambie la muestra para usar indexOf si está disponible, solo para que las personas que copien y peguen este código a ciegas obtendrán el mejor rendimiento posible.
orip

1
@cbmeeks sí, definitivamente se necesita cuidado. Probablemente fue un caso de hacer for (o in array)lo que no debería hacerse al recorrer la matriz en general ...
Damir Zekić

1
La mejor manera de hacerlo es verificar si [1, 2, 3] .indexOf (1)> -1
Devin G Rhode

207

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 no ofrece 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 revela una búsqueda rápida en Google (por ejemplo, esta )


en realidad, hay un ejemplo de la implementación de la extensión indexOf para navegadores que no lo 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 admiten (es decir, IE7), también intentarán recorrer esta función cuando recorran los elementos de la matriz. asqueroso.
CpILL


¿Es aplicable verificar el Objeto? no creo que funcione en el caso del Objeto
Himesh Aadeshara

169

Presenta ECMAScript 7 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

A diferencia indexOf, que usa la comparación estricta de igualdad , se includescompara con el algoritmo de igualdad SameValueZero . Eso significa que puede detectar si una matriz incluye un NaN:

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

También a diferencia indexOf, includesno omite los índices faltantes:

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

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


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

1
También es relevante, la tabla de compatibilidad ES7 (parece que Chrome la admite ahora)
styfle

¿Es aplicable verificar el Objeto? no creo que funcione en el caso del Objeto
Himesh Aadeshara

128

Las respuestas principales suponen tipos primitivos, pero si desea averiguar si una matriz contiene un objeto con algún rasgo, Array.prototype.some () es una solución muy 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 cancela una vez que se encuentra el elemento, por lo que se ahorran ciclos de iteración innecesarios.

Además, se ajusta muy bien en una ifdeclaración ya que devuelve un valor booleano:

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

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


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

1
Trabajando en Nodo> = 8.10 para AWS Node.js Lambda, así que esto es genial. ¡Solución muy limpia y simple! 👍🏻
Jordania

1
@jamess Puede estar bien soportado, pero recuerde que Arrow functionsen este ejemplo no está tan bien soportado. Para obtener más detalles, consulte aquí: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Kamil Witkowski el

¿Algún cortocircuito? ¿O itera toda la matriz incluso si se encuentra un valor?
Douglas Gaskell el

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

112

Digamos que has definido una matriz así:

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

A continuación se presentan tres formas de verificar si hay una 3allí. Todos regresan ya sea trueo false.

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

array.includes(3) // true

Como método de matriz personalizado (pre 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

Devuelve verdadero si "b" está en la matriz "a" ... No sé cómo explicarlo ...
william malo

44
Esta parte no entiendo "!! ~". Y creo que esto no funcionará en IE8 porque IE8 no admite indexOf () en el objeto Array.
svlada

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

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

2
Yo diría que la falta de conocimiento sobre los efectos de los operadores booleanos no es profesional. 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 los principales frameworks JS.
okdewit

79

Aquí hay una implementación compatible con JavaScript 1.6 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;
        };
}

Esto se ve genial, pero un poco confundido: * ¿No son equivalentes las pruebas en las líneas 1 y 3? * ¿No sería mejor probar el prototipo y agregar la función a Array.prototype si es necesario?
Avi Flax

10
No son equivalentes. [].indexOfes una abreviatura de Array.prototype.indexOf. Los programadores Javascript paranoicos-defensivos evitan extender prototipos nativos a toda costa.
Már Örlygsson

1
¿No está [].indexOfcreando una nueva matriz y luego accediendo indexOf, mientras Array.prototype.indexOfsolo accede al prototipo directamente?
alex

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

57

Utilizar:

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

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

25
x ? true : falseSuele ser redundante. Es aquí.
Ry-

@minitech ¿Por qué dices que es redundante?
Matías Cánepa

8
array.indexOf(search) >= 0Ya es un booleano. Justo return array.indexOf(search) >= 0.
Ry-

@minitech bien gracias! En realidad no sabía que tal construcción podría ser devuelta. TIL algo nuevo.
Matías Cánepa

Literalmente, cualquier construcción en JavaScript se puede devolver
BT

49

Ampliar el Arrayobjeto JavaScript es una muy mala idea porque introduce nuevas propiedades (sus métodos personalizados) en for-inbucles que pueden romper los scripts existentes. Hace unos años, los autores de la biblioteca Prototype tuvieron 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.


22
Estoy en desacuerdo. Los bucles for-in no deben usarse para matrices precisamente por este motivo. El uso de bucles for-in se interrumpirá cuando se use una de las bibliotecas js populares
Tomás

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

33

Un trazador de líneas:

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

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


28

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


19

Una esperanza bidireccional indexOf/ lastIndexOfalternativa más rápida

2015

Si bien 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 slow indexOf / lastIndexOf.

Ya se ha encontrado una forma eficaz, mirando las respuestas principales. De esos elegí la containsfunció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.

También prefiero whilesobre for, pero por una razón no específica terminé escribiendo la función con un bucle for. También se podría hacer con un while --.

Tenía curiosidad si la iteración era mucho más lenta si revisaba 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 insertar una matriz con un valor, usar lastIndexOf sigue siendo probablemente la mejor solución, pero si tiene que viajar a través de grandes matrices y el resultado podría estar en todas partes, esta podría ser una solución sólida para acelerar las cosas.

Bidirectional 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 la containsfunción para reflejar la salida indexOf & lastIndexOf (básicamente, truecon indexy falsecon -1). Eso no debería dañarlo.

La variante 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, cadena o lo que sea.

Y aquí está la whilevariante:

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 realiza tres comprobaciones por iteración, pero esto solo es posible con un cálculo más largo que causa la desaceleración del código.

http://jsperf.com/bidirectionalindexof/2


18

Actuación

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

  • Las soluciones basadas en JSON, Sety sorprendentemente find(K, N, O) son más lentas 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ápidas 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 caché de la CPU funciona .
  • También ejecuté la prueba de matriz grande cuando el elemento buscado estaba en la posición 66% de la longitud de la matriz, y las soluciones basadas en for(C, D, E) dan resultados similares (~ 630 operaciones / seg, pero la E en safari y firefox era 10- 20% más lento que C y D)

Resultados

ingrese la descripción de la imagen aquí

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 centro de la matriz.

Array pequeño - 10 elementos

Puedes realizar pruebas en tu máquina AQUÍ

ingrese la descripción de la imagen aquí

Matriz grande - 1.000.000 elementos

Puedes realizar pruebas en tu máquina AQUÍ

ingrese la descripción de la imagen aquí


16

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


16
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 matriz si se encuentra, o -1 si no se encuentra


16

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

15

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 una ordenación por inserción en su matriz (coloque nuevos objetos en el lugar correcto)
  2. Realice la actualización de objetos como eliminar + operación de inserción ordenada y
  3. Use una búsqueda binaria en su contains(a, obj).

2
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

13

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 qué usar JSON.stringify?

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

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

Prima

ES6 one-liner no optimizado:

[{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


Se actualizó la containsfunción con una optimización de rendimiento. Gracias a ti por señalarlo.


Este fragmento de código en particular puede funcionar en IE6 (no lo he probado), pero IE no admitió ES5 hasta IE9.
Mark Reed

Por razones de rendimiento, debe evitar encadenar. Al menos debe evitar JSON.stringify el "obj" en cada bucle porque es costoso y ralentizará su aplicación. Por lo tanto, debe capturarlo antes del ciclo for en una variable temporal
inicia el

1
@inicio buen punto. Actualizó la includesfunción con su sugerencia. Ejecuté jsperf con mi función. Es aproximadamente 5 veces más lento que lo que incluye Lodash. Aunque lodash no se puede comparar por su valor y no puede encontrar {a: 1}en [{a: 1}]. No sé si alguna biblioteca lo hace. Pero tengo curiosidad por saber si hay alguna forma más efectiva 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.
Heretic Monkey

1
@ HereticMonkey, cierto. Es por eso que agregué la sort-keysnota en la parte inferior
Igor Barbashin el

12

Use alguna función de lodash .

Es conciso, preciso y tiene un gran soporte multiplataforma.

La respuesta aceptada ni siquiera cumple 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 existe un valor escalar en una matriz de escalares ...

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

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

Para manejar tanto escalares como objetos, puede hacer esto:

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

10

ECMAScript 6 tiene una elegante propuesta de búsqueda.

El método find ejecuta la función de devolución de llamada una vez para cada elemento presente en la matriz hasta que encuentra una donde la devolución de llamada devuelve un valor verdadero. Si se encuentra dicho elemento, buscar inmediatamente devuelve el valor de ese elemento. De lo contrario, encuentra devoluciones indefinidas. la devolución de llamada se invoca solo para í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 de MDN sobre 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 siguientes 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;
    }
  });
}


9

Si bien array.indexOf(x)!=-1es 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 va a cambiar, puede convertir su matriz en una tabla hash, luego hacer table[x]!==undefinedo ===undefined:

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

Manifestación:

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

(Desafortunadamente, si bien 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 adelante. JavaScript no tiene suficientes enlaces para le permite mantener este estado, a diferencia de Python, por ejemplo).


9

Se puede usar Set 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'));


55
Creo que 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); }
Gordon Bean

8

Utilizar:

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

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

Manifestación

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


55
Esto ya se publicó hace un año y medio, no es necesario repetirlo.
Shadow Wizard es Ear For You el

3
En realidad, no ha sido publicado. No como una respuesta, sino como un comentario a una respuesta, y aun así no es claro y conciso. Gracias por publicarlo, Mina Gabriel.
T.CK

6

OK, ¡puedes optimizar tu código para obtener el resultado!

Hay muchas maneras de hacer esto que son más limpias y mejores, pero solo quería obtener su patrón y aplicarlo usando JSON.stringify, simplemente haga algo como esto en su 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;
}

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.
Heretic Monkey

5

De ninguna manera el mejor, pero me estaba poniendo creativo y añadiendo 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'));


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

@bryc tal vez la solución aceptada, u otra solución desde aquí. Si no le interesa mucho el rendimiento, puede usar esto
sqram

5

Sorprendido de 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 él.

Array.prototype. indexOf -> (devuelve índice o -1 ) se usa generalmente para encontrar el índice del elemento en la matriz. Esto también se puede usar para buscar objetos, pero solo funciona si está pasando referencias 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

Array.prototype. incluye -> (devuelve verdadero o falso )

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

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

Array.prototype. find -> (toma la devolución de llamada, devuelve el primer 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

Array.prototype. findIndex -> (toma la devolución de llamada, devuelve el í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 toma una devolución de llamada, podemos recuperar cualquier objeto (incluso si no tenemos la referencia) de la matriz configurando creativamente la verdadera condición.


5

Una solución simple para este requisito es usar 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 código siguiente.

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

Obtendrá 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.


5

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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.