objetos - indexof javascript ejemplo
Por qué Array.indexOf no encuentra objetos de aspecto idéntico (8)
indexOf compara searchElement con elementos de la matriz utilizando igualdad estricta (el mismo método utilizado por el operador === o triple-equal).
No puede usar ===
para verificar la igualdad de un objeto.
Como @RobG señaló
Tenga en cuenta que, por definición, dos objetos nunca son iguales, incluso si tienen exactamente los mismos nombres de propiedades y valores.
objectA === objectB
si y solo si objectA y objectB hacen referencia al mismo objeto.
Simplemente puede escribir una función indexOf personalizada para verificar el objeto.
function myIndexOf(o) {
for (var i = 0; i < arr.length; i++) {
if (arr[i].x == o.x && arr[i].y == o.y) {
return i;
}
}
return -1;
}
Tengo una matriz con objetos.
Algo como esto:
var arr = new Array(
{x:1, y:2},
{x:3, y:4}
);
Cuando intento:
arr.indexOf({x:1, y:2});
Devuelve -1
.
Si tengo cadenas o números u otro tipo de elementos pero objeto, entonces indexOf()
funciona bien.
¿Alguien sabe por qué y qué debo hacer para buscar los elementos del objeto en la matriz?
Por supuesto, me refiero a las formas, excepto a hacer llaves de hash de cadena para objetos y dárselos a la matriz ...
Aquí hay otra solución, donde pasa una función de comparación como parámetro:
function indexOf(array, val, from, compare) {
if (!compare) {
if (from instanceof Function) {
compare = from;
from = 0;
}
else return array.__origIndexOf(val, from);
}
if (!from) from = 0;
for (var i=from ; i < array.length ; i++) {
if (compare(array[i], val))
return i;
}
return -1;
}
// Save original indexOf to keep the original behaviour
Array.prototype.__origIndexOf = Array.prototype.indexOf;
// Redefine the Array.indexOf to support a compare function.
Array.prototype.indexOf = function(val, from, compare) {
return indexOf(this, val, from, compare);
}
Puede usarlo de esta manera:
indexOf(arr, {x:1, y:2}, function (a,b) {
return a.x == b.x && a.y == b.y;
});
arr.indexOf({x:1, y:2}, function (a,b) {
return a.x == b.x && a.y == b.y;
});
arr.indexOf({x:1, y:2}, 1, function (a,b) {
return a.x == b.x && a.y == b.y;
});
Lo bueno es que todavía llama al índice original de si no se pasa la función de comparación.
[1,2,3,4].indexOf(3);
Como nadie mencionó la función incorporada Array.prototype.findIndex (), me gustaría mencionar que hace exactamente lo que necesita el autor.
El método findIndex () devuelve el índice del primer elemento en la matriz que satisface la función de prueba proporcionada. De lo contrario, se devuelve -1.
var array1 = [5, 12, 8, 130, 44];
function findFirstLargeNumber(element) {
return element > 13;
}
console.log(array1.findIndex(findFirstLargeNumber));
// expected output: 3
En tu caso sería:
arr.findIndex(function(element) {
return element.x == 1 && element.y == 2;
});
O usando ES6
arr.findIndex( element => element.x == 1 && element.y == 2 );
Más información con el ejemplo anterior: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex
Como se señaló, dos objetos nunca son iguales, pero las referencias pueden ser iguales si están en el mismo objeto, para que el código haga lo que desee:
var a = {x:1, y:2};
var b = {x:3, y:4};
var arr = [a, b];
alert(arr.indexOf(a)); // 0
Editar
Aquí hay una función specialIndexOf más general. Tenga en cuenta que espera que los valores de los objetos sean primitivos, de lo contrario, debe ser más riguroso.
function specialIndexOf(arr, value) {
var a;
for (var i=0, iLen=arr.length; i<iLen; i++) {
a = arr[i];
if (a === value) return i;
if (typeof a == ''object'') {
if (compareObj(arr[i], value)) {
return i;
}
} else {
// deal with other types
}
}
return -1;
// Extremely simple function, expects the values of all
// enumerable properties of both objects to be primitives.
function compareObj(o1, o2, cease) {
var p;
if (typeof o1 == ''object'' && typeof o2 == ''object'') {
for (p in o1) {
if (o1[p] != o2[p]) return false;
}
if (cease !== true) {
compareObj(o2, o1, true);
}
return true;
}
}
}
var a = new String(''fred'');
var b = new String(''fred'');
var arr = [0,1,a];
alert(specialIndexOf(arr, b)); // 2
Esos objetos no son iguales.
Debes implementar tu propia función.
Puede hacer eso, por ejemplo:
var index = -1;
arr.forEach(function(v, i) {
if (this.x==v.x && this.y==v.y) index=i;
}, searched);
donde searched
es uno de sus objetos (o no).
(Lo implementaría con un simple bucle pero es más bonito con foreach)
Esto funciona sin código personalizado
var arr, a, found;
arr = [{x: 1, y: 2}];
a = {x: 1, y: 2};
found = JSON.stringify(arr).indexOf(JSON.stringify(a)) > - 1;
// found === true
Nota: esto no da el índice real, solo dice si su objeto existe en la estructura de datos actual
Parece que no estaba interesado en este tipo de respuesta, pero es lo más simple para otros interesados:
var arr = new Array(
{x:1, y:2},
{x:3, y:4}
);
arr.map(function(obj) {
return objStr(obj);
}).indexOf(objStr({x:1, y:2}));
function objStr(obj) {
return "(" + obj.x + ", " + obj.y + ")"
}
Porque dos objetos separados no son ===
entre sí, e indexOf
usa ===
. (Tampoco son ==
uno para el otro).
Ejemplo:
var a = {x:1, y:2};
var b = {x:1, y:2};
console.log(a === b);
===
y ==
prueba si sus operandos se refieren al mismo objeto , no si se refieren a objetos equivalentes (objetos con el mismo prototipo y propiedades).