¿Cómo verifico si una matriz incluye un valor en JavaScript?
¿Cuál es la forma más concisa y eficaz de saber si una matriz de JavaScript contiene un valor?
Esta es la única manera 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?
Esto está muy relacionado con la pregunta de Stack Overflow. ¿La mejor manera de encontrar un elemento en una matriz de JavaScript? que aborda la búsqueda de objetos en una matriz usando indexOf
.
Los navegadores modernos tienen Array#includes
, que hace exactamente eso y es ampliamente compatible con 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:
- jQuery:
$.inArray(value, array, [fromIndex])
- Underscore.js:
_.contains(array, value)
(también conocido como_.include
y_.includes
) - Kit de herramientas de Dojo:
dojo.indexOf(array, value, [fromIndex, findLast])
- Prototipo:
array.indexOf(value)
- MooHerramientas:
array.indexOf(value)
- MochiKit:
findValue(array, value)
- MS Ajax:
array.indexOf(value)
- Extensión:
Ext.Array.contains(array, value)
- Lodash:
_.includes(array, value, [from])
(es_.contains
anterior a 4.0.0) - Ramda:
R.includes(value, array)
Observe que algunos marcos implementan esto como una función, mientras que otros agregan la función al prototipo de matriz.
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 una prueba comparativa realizada en navegadores de esa época. Puede que no sea relevante para los contextos de ejecución JS modernos. Si necesita una solución fácil, busque otras respuestas. Si necesita el mejor rendimiento, compare usted mismo 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 un while
bucle decreciente 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 ampliar 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
Las respuestas principales asumen tipos primitivos, pero si desea saber 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 cancela una vez que se encuentra el elemento, por lo que se ahorran ciclos de iteración innecesarios.
Además, encaja muy bien en una if
declaración ya que devuelve un valor booleano:
if (items.some(item => item.a === '3')) {
// do something
}
* Como Jamess señaló en el comentario, en el momento de esta respuesta, septiembre de 2018, Array.prototype.some()
es totalmente compatible: tabla de soporte de caniuse.com
indexOf
tal vez, pero es una "extensión de 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 no ofrece ningú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 lo revela una búsqueda rápida en Google (por ejemplo, este ).
ECMAScript 7 presenta Array.prototype.includes
.
Se puede utilizar 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 de indexOf
, que utiliza Strict Equality Comparison , includes
compara utilizando el algoritmo de igualdad SameValueZero . Eso significa que puedes detectar si una matriz incluye NaN
:
[1, 2, NaN].includes(NaN); // true
Además, a diferencia de indexOf
, includes
no omite los índices faltantes:
new Array(5).includes(undefined); // true
Se puede rellenar para que funcione en todos los navegadores.
Digamos que has definido una matriz como esta:
const array = [1, 2, 3, 4]
A continuación se muestran tres formas de comprobar si hay un 3
allí. Todos regresan o true
o false
.
Método Native Array (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 sencilla
const includes = (a, v) => a.indexOf(v) !== -1
includes(array, 3) // true