tipos - ¿La mejor manera de encontrar si un elemento está en una matriz de JavaScript?
tablas dinamicas html javascript (8)
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
A partir de ECMAScript 2016 puede usar 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:
Versión de Mozilla''s (ECMA-262):
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; }; }
La versión de 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; }; }
versión de roosteronacid :
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); } );
Aquí hay algo de meta-conocimiento para usted: si desea saber qué puede hacer con un Array, consulte la documentación.
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array
Ahí verás referencia a indexOf, agregado en Javascript 1.6.
Depende de tu propósito. Si programa para la web, evite indexOf
, no es compatible con Internet Explorer 6 (¡muchos de ellos todavía 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 haría una return false;
Al final de tu rutina, para devolver un verdadero booleano ...
Primero, implemente indexOf
en JavaScript para los navegadores que aún no lo tienen. Por ejemplo, vea los extras de la matriz de Erik Arvidsson (también, la 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á interesado en la microoptimización, he adaptado los benchmarks que se vincula roosterononacid en los comentarios, para realizar una búsqueda de puntos de referencia en matrices . Sin embargo, son bastante toscos, una investigación completa probaría matrices con diferentes tipos, diferentes longitudes y la búsqueda de objetos que ocurren en diferentes lugares.
Si está utilizando jQuery:
$.inArray(5 + 5, [ "8", "9", "10", 10 + "" ]);
Para obtener más información: http://api.jquery.com/jQuery.inArray/
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 la misma cosa). Si la matriz está ordenada, puedes hacer una búsqueda binaria, que funciona así:
- Elija el elemento central de la matriz.
- ¿Es el elemento que estás buscando 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.
- 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ás tu elemento o no te 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.
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 = {}
''contenedor''. Estos deberían ayudarte a detectar correctamente los arrays.
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 desea verificar 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;
}
[] .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 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