javascript - son - comparar valores js
¿Cómo comprobar si dos matrices son iguales a JavaScript? (16)
Esta pregunta ya tiene una respuesta aquí:
- ¿Cómo comparar matrices en JavaScript? 44 respuestas
var a = [1, 2, 3];
var b = [3, 2, 1];
var c = new Array(1, 2, 3);
alert(a == b + "|" + b == c);
¿Cómo puedo verificar estas matrices por igualdad y obtener un método que devuelva true
si son iguales?
¿JQuery ofrece algún método para esto?
Compruebe cada valor por un bucle for una vez que haya verificado el tamaño de la matriz.
function equalArray(a, b) {
if (a.length === b.length) {
for (var i = 0; i < a.length; i++) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
} else {
return false;
}
}
Con JavaScript versión 1.6 es tan fácil como esto:
Array.prototype.equals = function( array ) {
return this.length == array.length &&
this.every( function(this_i,i) { return this_i == array[i] } )
}
Por ejemplo, [].equals([])
da true
, mientras [1,2,3].equals( [1,3,2] )
da false
.
Esto es lo que deberías hacer. Por favor, no use stringify
ni < >
.
function arraysEqual(a, b) {
if (a === b) return true;
if (a == null || b == null) return false;
if (a.length != b.length) return false;
// If you don''t care about the order of the elements inside
// the array, you should sort both arrays here.
for (var i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) return false;
}
return true;
}
Incluso si esto parece muy simple, a veces es realmente útil. Si todo lo que necesita es ver si dos matrices tienen los mismos elementos y están en el mismo orden, intente esto:
[1, 2, 3].toString() == [1, 2, 3].toString()
true
[1, 2, 3,].toString() == [1, 2, 3].toString()
true
[1,2,3].toString() == [1, 2, 3].toString()
true
Sin embargo, esto no funciona para casos avanzados de modo tales como:
[[1,2],[3]].toString() == [[1],[2,3]].toString()
true
Depende de lo que necesites
Maneja todas las cosas posibles e incluso se refiere a sí mismo en la estructura del objeto. Puedes ver el ejemplo al final del código.
var deepCompare = (function() {
function internalDeepCompare (obj1, obj2, objects) {
var i, objPair;
if (obj1 === obj2) {
return true;
}
i = objects.length;
while (i--) {
objPair = objects[i];
if ( (objPair.obj1 === obj1 && objPair.obj2 === obj2) ||
(objPair.obj1 === obj2 && objPair.obj2 === obj1) ) {
return true;
}
}
objects.push({obj1: obj1, obj2: obj2});
if (obj1 instanceof Array) {
if (!(obj2 instanceof Array)) {
return false;
}
i = obj1.length;
if (i !== obj2.length) {
return false;
}
while (i--) {
if (!internalDeepCompare(obj1[i], obj2[i], objects)) {
return false;
}
}
}
else {
switch (typeof obj1) {
case "object":
// deal with null
if (!(obj2 && obj1.constructor === obj2.constructor)) {
return false;
}
if (obj1 instanceof RegExp) {
if (!(obj2 instanceof RegExp && obj1.source === obj2.source)) {
return false;
}
}
else if (obj1 instanceof Date) {
if (!(obj2 instanceof Date && obj1.getTime() === obj2.getTime())) {
return false;
}
}
else {
for (i in obj1) {
if (obj1.hasOwnProperty(i)) {
if (!(obj2.hasOwnProperty(i) && internalDeepCompare(obj1[i], obj2[i], objects))) {
return false;
}
}
}
}
break;
case "function":
if (!(typeof obj2 === "function" && obj1+"" === obj2+"")) {
return false;
}
break;
default: //deal with NaN
if (obj1 !== obj2 && obj1 === obj1 && obj2 === obj2) {
return false;
}
}
}
return true;
}
return function (obj1, obj2) {
return internalDeepCompare(obj1, obj2, []);
};
}());
/*
var a = [a, undefined, new Date(10), /.+/, {a:2}, function(){}, Infinity, -Infinity, NaN, 0, -0, 1, [4,5], "1", "-1", "a", null],
b = [b, undefined, new Date(10), /.+/, {a:2}, function(){}, Infinity, -Infinity, NaN, 0, -0, 1, [4,5], "1", "-1", "a", null];
deepCompare(a, b);
*/
No hay una manera fácil de hacer esto. Lo necesitaba también, pero quería una función que pueda tomar dos variables y probar la igualdad. Eso incluye valores no objeto, objetos, matrices y cualquier nivel de anidamiento.
En su pregunta, menciona que desea ignorar el orden de los valores en una matriz. Mi solución no hace eso inherentemente, pero puede lograrlo ordenando las matrices antes de comparar por igualdad
También quería la opción de convertir no objetos en cadenas de modo que [1,2] === ["1", 2]
Como mi proyecto usa UnderscoreJs, decidí convertirlo en una función mixin en lugar de independiente.
Puedes probarlo en http://jsfiddle.net/nemesarial/T44W4/
Aquí está mi mxin:
_.mixin({
/**
Tests for the equality of two variables
valA: first variable
valB: second variable
stringifyStatics: cast non-objects to string so that "1"===1
**/
equal:function(valA,valB,stringifyStatics){
stringifyStatics=!!stringifyStatics;
//check for same type
if(typeof(valA)!==typeof(valB)){
if((_.isObject(valA) || _.isObject(valB))){
return false;
}
}
//test non-objects for equality
if(!_.isObject(valA)){
if(stringifyStatics){
var valAs=''''+valA;
var valBs=''''+valB;
ret=(''''+valA)===(''''+valB);
}else{
ret=valA===valB;
}
return ret;
}
//test for length
if(_.size(valA)!=_.size(valB)){
return false;
}
//test for arrays first
var isArr=_.isArray(valA);
//test whether both are array or both object
if(isArr!==_.isArray(valB)){
return false;
}
var ret=true;
if(isArr){
//do test for arrays
_.each(valA,function(val,idx,lst){
if(!ret){return;}
ret=ret && _.equal(val,valB[idx],stringifyStatics);
});
}else{
//do test for objects
_.each(valA,function(val,idx,lst){
if(!ret){return;}
//test for object member exists
if(!_.has(valB,idx)){
ret=false;
return;
}
// test for member equality
ret=ret && _.equal(val,valB[idx],stringifyStatics);
});
}
return ret;
}
});
Así es como lo usas:
_.equal([1,2,3],[1,2,"3"],true)
Para demostrar el anidamiento, puedes hacer esto:
_.equal(
[''a'',{b:''b'',c:[{''someId'':1},2]},[1,2,3]],
[''a'',{b:''b'',c:[{''someId'':"1"},2]},["1",''2'',3]]
,true);
Para valores primitivos como números y cadenas, esta es una solución fácil:
a = [1,2,3]
b = [3,2,1]
a.sort().toString() == b.sort().toString()
La llamada a sort()
asegurará que el orden de los elementos no importe. La llamada toString()
creará una cadena con los valores separados por comas para que ambas cadenas se puedan probar en busca de igualdad.
Según la answer Tim James y el comentario de Fox32, lo siguiente debería verificar los nulos, suponiendo que dos nulos no son iguales.
function arrays_equal(a,b) { return !!a && !!b && !(a<b || b<a); }
> arrays_equal([1,2,3], [1,3,4])
false
> arrays_equal([1,2,3], [1,2,3])
true
> arrays_equal([1,3,4], [1,2,3])
false
> arrays_equal(null, [1,2,3])
false
> arrays_equal(null, null)
false
Si desea comprobar matrices de objetos para la igualdad y el orden NO importa, es decir,
areEqual([{id: "0"}, {id: "1"}], [{id: "1"}, {id: "0"}]) // true
querrás ordenar las matrices primero. lodash tiene todas las herramientas que necesitará, al combinar sortBy
e isEqual
:
// arr1 & arr2: Arrays of objects
// sortProperty: the property of the object with which you want to sort
// Note: ensure every object in both arrays has your chosen sortProperty
// For example, arr1 = [{id: "v-test_id0"}, {id: "v-test_id1"}]
// and arr2 = [{id: "v-test_id1"}, {id: "v-test_id0"}]
// sortProperty should be ''id''
function areEqual (arr1, arr2, sortProperty) {
return _.areEqual(_.sortBy(arr1, sortProperty), _.sortBy(arr2, sortProperty))
}
EDITAR: Como sortBy
devuelve una nueva matriz, no es necesario clonar las matrices antes de ordenarlas. Las matrices originales no serán mutadas.
Tenga en cuenta que para lodash''s isEqual
, el orden sí importa . El ejemplo anterior devolverá false
si sortBy
no se aplica primero a cada matriz.
Si está utilizando lodash y no desea modificar ninguna matriz, puede usar la función _.xor () . Compara las dos matrices como conjuntos y devuelve el conjunto que contiene su diferencia. Si la longitud de esta diferencia es cero, las dos matrices son esencialmente iguales:
var a = [1, 2, 3];
var b = [3, 2, 1];
var c = new Array(1, 2, 3);
_.xor(a, b).length === 0
true
_.xor(b, c).length === 0
true
Usando map()
y reduce()
:
function arraysEqual (a1, a2) {
return a1 === a2 || (
a1 !== null && a2 !== null &&
a1.length === a2.length &&
a1
.map(function (val, idx) { return val === a2[idx]; })
.reduce(function (prev, cur) { return prev && cur; }, true)
);
}
jQuery no tiene un método para comparar matrices. Sin embargo, la biblioteca Underscore (o la biblioteca comparable de Lodash) tiene dicho método: isEqual , y puede manejar una variedad de otros casos (como literales de objetos) también. Para cumplir con el ejemplo proporcionado:
var a=[1,2,3];
var b=[3,2,1];
var c=new Array(1,2,3);
alert(_.isEqual(a, b) + "|" + _.isEqual(b, c));
Por cierto: subrayado tiene muchos otros métodos que jQuery también falta, por lo que es un gran complemento para jQuery.
EDITAR: Como se ha señalado en los comentarios, lo anterior ahora solo funciona si ambas matrices tienen sus elementos en el mismo orden, es decir:
_.isEqual([1,2,3], [1,2,3]); // true
_.isEqual([1,2,3], [3,2,1]); // false
Afortunadamente Javascript tiene un método incorporado para resolver este problema exacto, sort
:
_.isEqual([1,2,3].sort(), [3,2,1].sort()); // true
jQuery tiene dicho método para una comparación recursiva profunda .
Un control de igualdad estricto de propósito general de cosecha propia podría verse de la siguiente manera:
function deepEquals(obj1, obj2, parents1, parents2) {
"use strict";
var i;
// compare null and undefined
if (obj1 === undefined || obj2 === undefined ||
obj1 === null || obj2 === null) {
return obj1 === obj2;
}
// compare primitives
if (typeof (obj1) !== ''object'' || typeof (obj2) !== ''object'') {
return obj1.valueOf() === obj2.valueOf();
}
// if objects are of different types or lengths they can''t be equal
if (obj1.constructor !== obj2.constructor || (obj1.length !== undefined && obj1.length !== obj2.length)) {
return false;
}
// iterate the objects
for (i in obj1) {
// build the parents list for object on the left (obj1)
if (parents1 === undefined) parents1 = [];
if (obj1.constructor === Object) parents1.push(obj1);
// build the parents list for object on the right (obj2)
if (parents2 === undefined) parents2 = [];
if (obj2.constructor === Object) parents2.push(obj2);
// walk through object properties
if (obj1.propertyIsEnumerable(i)) {
if (obj2.propertyIsEnumerable(i)) {
// if object at i was met while going down here
// it''s a self reference
if ((obj1[i].constructor === Object && parents1.indexOf(obj1[i]) >= 0) || (obj2[i].constructor === Object && parents2.indexOf(obj2[i]) >= 0)) {
if (obj1[i] !== obj2[i]) {
return false;
}
continue;
}
// it''s not a self reference so we are here
if (!deepEquals(obj1[i], obj2[i], parents1, parents2)) {
return false;
}
} else {
// obj2[i] does not exist
return false;
}
}
}
return true;
};
Pruebas:
// message is displayed on failure
// clean console === all tests passed
function assertTrue(cond, msg) {
if (!cond) {
console.log(msg);
}
}
var a = ''sdf'',
b = ''sdf'';
assertTrue(deepEquals(b, a), ''Strings are equal.'');
b = ''dfs'';
assertTrue(!deepEquals(b, a), ''Strings are not equal.'');
a = 9;
b = 9;
assertTrue(deepEquals(b, a), ''Numbers are equal.'');
b = 3;
assertTrue(!deepEquals(b, a), ''Numbers are not equal.'');
a = false;
b = false;
assertTrue(deepEquals(b, a), ''Booleans are equal.'');
b = true;
assertTrue(!deepEquals(b, a), ''Booleans are not equal.'');
a = null;
assertTrue(!deepEquals(b, a), ''Boolean is not equal to null.'');
a = function () {
return true;
};
assertTrue(deepEquals(
[
[1, 1, 1],
[2, ''asdf'', [1, a]],
[3, {
''a'': 1.0
},
true]
],
[
[1, 1, 1],
[2, ''asdf'', [1, a]],
[3, {
''a'': 1.0
},
true]
]), ''Arrays are equal.'');
assertTrue(!deepEquals(
[
[1, 1, 1],
[2, ''asdf'', [1, a]],
[3, {
''a'': 1.0
},
true]
],
[
[1, 1, 1],
[2, ''asdf'', [1, a]],
[3, {
''a'': ''1''
},
true]
]), ''Arrays are not equal.'');
a = {
prop: ''val''
};
a.self = a;
b = {
prop: ''val''
};
b.self = a;
assertTrue(deepEquals(b, a), ''Immediate self referencing objects are equal.'');
a.prop = ''shmal'';
assertTrue(!deepEquals(b, a), ''Immediate self referencing objects are not equal.'');
a = {
prop: ''val'',
inside: {}
};
a.inside.self = a;
b = {
prop: ''val'',
inside: {}
};
b.inside.self = a;
assertTrue(deepEquals(b, a), ''Deep self referencing objects are equal.'');
b.inside.self = b;
assertTrue(!deepEquals(b, a), ''Deep self referencing objects are not equeal. Not the same instance.'');
b.inside.self = {foo: ''bar''};
assertTrue(!deepEquals(b, a), ''Deep self referencing objects are not equal. Completely different object.'');
a = {};
b = {};
a.self = a;
b.self = {};
assertTrue(!deepEquals(b, a), ''Empty object and self reference of an empty object.'');
Este método apesta, pero lo dejé aquí como referencia para que otros eviten esta ruta:
Usar la Opción 1 de @ninjagecko funcionó mejor para mí:
Array.prototype.equals = function(array) {
return array instanceof Array && JSON.stringify(this) === JSON.stringify(array) ;
}
a = [1, [2, 3]]
a.equals([[1, 2], 3]) // false
a.equals([1, [2, 3]]) // true
También manejará el caso nulo e indefinido, ya que estamos agregando esto al prototipo de matriz y comprobando que el otro argumento también sea una matriz.
Opción 1
La opción más fácil, funciona en casi todos los casos, excepto que null
! == undefined
pero ambos se convierten a la representación JSON null
y se consideran iguales:
function arraysEqual(a1,a2) {
/* WARNING: arrays must not contain {objects} or behavior may be undefined */
return JSON.stringify(a1)==JSON.stringify(a2);
}
( Esto podría no funcionar si su matriz contiene objetos. Si esto funciona con objetos depende de si la implementación de JSON ordena las claves. Por ejemplo, el JSON de {1:2,3:4}
puede o no ser igual a {3:4,1:2}
; esto depende de la implementación y la especificación no garantiza en absoluto. [Actualización de 2017: en realidad, la especificación ES6 ahora garantiza que las claves de objeto se iterarán en el orden en que se insertaron. SI la implementación de JSON.stringify sigue esto, los objetos iguales se codificarán en valores iguales. Se necesita más investigación.] Al menos en Chrome, la función JSON.stringify tiende a devolver las claves en el orden en que fueron definidas (al menos eso he notado), pero este comportamiento es muy sujeto a cambios en cualquier punto y no se debe confiar en ellos. Si decide no usar objetos en sus listas, esto debería funcionar bien. Si tiene objetos en su lista que tienen una identificación única, puede hacer a1.map(function(x)}{return {id:x.uniqueId}})
. Si tiene objetos arbitrarios en su lista , puede seguir leyendo para la opción n. ° 2).
Esto también funciona para matrices anidadas.
Sin embargo, es un poco ineficiente debido a la sobrecarga de crear estas cadenas y recolectarlas.
opcion 2
Opción más "apropiada", que puede anular para tratar casos especiales (como objetos regulares y objetos nulos / indefinidos y personalizados, si así lo desea):
// generally useful functions
function type(x) { // does not work in general, but works on JSONable objects we care about... modify as you see fit
// e.g. type(/asdf/g) --> "[object RegExp]"
return Object.prototype.toString.call(x);
}
function zip(arrays) {
// e.g. zip([[1,2,3],[4,5,6]]) --> [[1,4],[2,5],[3,6]]
return arrays[0].map(function(_,i){
return arrays.map(function(array){return array[i]})
});
}
// helper functions
function allCompareEqual(array) {
// e.g. allCompareEqual([2,2,2,2]) --> true
// does not work with nested arrays or objects
return array.every(function(x){return x==array[0]});
}
function isArray(x){ return type(x)==type([]) }
function getLength(x){ return x.length }
function allTrue(array){ return array.reduce(function(a,b){return a&&b},true) }
// e.g. allTrue([true,true,true,true]) --> true
// or just array.every(function(x){return x});
function allDeepEqual(things) {
// works with nested arrays
if( things.every(isArray) )
return allCompareEqual(things.map(getLength)) // all arrays of same length
&& allTrue(zip(things).map(allDeepEqual)); // elements recursively equal
//else if( this.every(isObject) )
// return {all have exactly same keys, and for
// each key k, allDeepEqual([o1[k],o2[k],...])}
// e.g. ... && allTrue(objectZip(objects).map(allDeepEqual))
//else if( ... )
// extend some more
else
return allCompareEqual(things);
}
Manifestación:
allDeepEqual([ [], [], [] ])
true
allDeepEqual([ [1], [1], [1] ])
true
allDeepEqual([ [1,2], [1,2] ])
true
allDeepEqual([ [[1,2],[3]], [[1,2],[3]] ])
true
allDeepEqual([ [1,2,3], [1,2,3,4] ])
false
allDeepEqual([ [[1,2],[3]], [[1,2],[],3] ])
false
allDeepEqual([ [[1,2],[3]], [[1],[2,3]] ])
false
allDeepEqual([ [[1,2],3], [1,[2,3]] ])
false
Para usar esto como una función normal, hazlo:
function allDeepEqual2() {
return allDeepEqual([].slice.call(arguments));
}
Manifestación:
allDeepEqual2([[1,2],3], [[1,2],3])
true
Opciones 3
editar : Es 2016 y mi respuesta anterior complicada me estaba molestando. Esta implementación recursiva e imperativa de "programación recursiva 101" mantiene el código realmente simple, y además falla en el punto más temprano posible (dándonos eficiencia). Tampoco genera estructuras de datos efímeras superfluas (no es que haya algo incorrecto en la programación funcional en general, sino que simplemente la mantiene limpia aquí).
Si quisiéramos aplicar esto a matrices no vacías de matrices, podríamos hacer seriesOfArrays.reduce (arraysEqual).
Esta es su propia función, en lugar de usar Object.defineProperties para adjuntarlo a Array.prototype, ya que eso fallaría con un error clave si pasamos en un valor indefinido (sin embargo, es una buena decisión de diseño si lo desea) .
Esto solo responde la pregunta original de OP.
function arraysEqual(a,b) {
/*
Array-aware equality checker:
Returns whether arguments a and b are == to each other;
however if they are equal-lengthed arrays, returns whether their
elements are pairwise == to each other recursively under this
definition.
*/
if (a instanceof Array && b instanceof Array) {
if (a.length!=b.length) // assert same length
return false;
for(var i=0; i<a.length; i++) // assert each element equal
if (!arraysEqual(a[i],b[i]))
return false;
return true;
} else {
return a==b; // if not both arrays, should be the same
}
}
Ejemplos:
arraysEqual([[1,2],3], [[1,2],3])
true
arraysEqual([1,2,3], [1,2,3,4])
false
arraysEqual([[1,2],[3]], [[1,2],[],3])
false
arraysEqual([[1,2],[3]], [[1],[2,3]])
false
arraysEqual([[1,2],3], undefined)
false
arraysEqual(undefined, undefined)
true
arraysEqual(1, 2)
false
arraysEqual(null, null)
true
arraysEqual(1, 1)
true
arraysEqual([], 1)
false
arraysEqual([], undefined)
false
arraysEqual([], [])
true
Si desea aplicar esto a estructuras de datos similares a JSON con objetos js, puede hacerlo. Afortunadamente, tenemos la garantía de que todas las claves de los objetos son únicas, así que itere sobre los objetos OwnProperties y ordénelas por clave, luego afirme que el conjunto de claves ordenadas es igual y que el conjunto de valores es igual y solo recurrente. Podemos extender esto para incluir Mapas también (donde las claves también son únicas). (Sin embargo, si ampliamos esto a Sets, nos encontramos con el problema de isomorfismo de árbol http://logic.pdmi.ras.ru/~smal/files/smal_jass08_slides.pdf - afortunadamente no es tan difícil como el isomorfismo gráfico general; De hecho, es un algoritmo O (#vertices) para resolverlo, pero puede ser muy complicado hacerlo de manera eficiente. El caso patológico es si tienes un conjunto formado por muchos objetos aparentemente indistinguibles, pero después de una inspección adicional algunos de esos objetos puede diferir a medida que profundiza en ellos. También puede evitar esto usando hash para rechazar casi todos los casos).
Opción 4: (continuación de la edición de 2016)
Esto debería funcionar con la mayoría de los objetos:
function deepEquals(a,b) {
if (a instanceof Array && b instanceof Array)
return arraysEqual(a,b);
if (Object.getPrototypeOf(a)===Object.prototype && Object.getPrototypeOf(b)===Object.prototype)
return objectsEqual(a,b);
if (a instanceof Map && b instanceof Map)
return mapsEqual(a,b);
if (a instanceof Set && b instanceof Set)
throw "Error: set equality by hashing not implemented."
if ((a instanceof ArrayBuffer || ArrayBuffer.isView(a)) && (b instanceof ArrayBuffer || ArrayBuffer.isView(b)))
return typedArraysEqual(a,b);
return a==b; // see note[1]
}
function arraysEqual(a,b) {
if (a.length!=b.length)
return false;
for(var i=0; i<a.length; i++)
if (!deepEquals(a[i],b[i]))
return false;
return true;
}
function objectsEqual(a,b) {
var aKeys = Object.getOwnPropertyNames(a);
var bKeys = Object.getOwnPropertyNames(b);
if (aKeys.length!=bKeys.length)
return false;
aKeys.sort();
bKeys.sort();
for(var i=0; i<aKeys.length; i++)
if (aKeys[i]!=bKeys[i]) // keys must be strings
return false;
return deepEquals(aKeys.map(k=>a[k]), aKeys.map(k=>b[k]));
}
function mapsEqual(a,b) {
if (a.size!=b.size)
return false;
var aPairs = Array.from(a);
var bPairs = Array.from(b);
aPairs.sort((x,y) => x[0]<y[0]);
bPairs.sort((x,y) => x[0]<y[0]);
for(var i=0; i<a.length; i++)
if (!deepEquals(aPairs[i][0],bPairs[i][0]) || !deepEquals(aPairs[i][1],bPairs[i][1]))
return false;
return true;
}
function typedArraysEqual(a,b) {
a = new Uint8Array(a);
b = new Uint8Array(b);
if (a.length != b.length)
return false;
for(var i=0; i<a.length; i++)
if (a[i]!=b[i])
return false;
return true;
}
Demo (no probado exhaustivamente):
var nineTen = new Float32Array(2);
nineTen[0]=9; nineTen[1]=10;
deepEquals(
[[1,[2,3]], 4, {a:5,b:6}, new Map([[''c'',7],[''d'',8]]), nineTen],
[[1,[2,3]], 4, {b:6,a:5}, new Map([[''d'',8],[''c'',7]]), nineTen]
)
(nota al margen: los mapas son diccionarios es6 que. No puedo decir si tienen O (1) u O (log (N)) rendimiento de búsqueda, pero en cualquier caso están ''ordenados'' en el sentido de que hacen un seguimiento del orden en el que los pares clave-valor se insertaron en ellos. Sin embargo, la semántica de si dos mapas deben ser iguales si los elementos se insertaron en un orden diferente en ellos es ambigua. A continuación, presento una implementación de muestra de un profundo que considera dos mapas iguales incluso si los elementos se insertaron en ellos en un orden diferente).
(nota [1]: es posible que desee sobrescribir la línea indicada con una noción personalizada de igualdad, que también deberá cambiar en las otras funciones en cualquier lugar que aparezca. Por ejemplo, desea o no quiere NaN = = NaN? Por defecto, este no es el caso. Hay cosas aún más raras como 0 == ''0''. Ver https://.com/a/5447170/711085 )
Debería poder extender lo anterior a WeakMaps, WeakSets. No estoy seguro de si tiene sentido extender a DataViews. También debería ser capaz de extenderse a RegExps probablemente, etc.
A medida que lo extiendes, te das cuenta de que haces muchas comparaciones innecesarias. Aquí es donde la función type
que definí anteriormente (solución # 2) puede ser útil; entonces puedes despachar al instante. Ya sea que valga la pena (posiblemente, no estoy seguro de cómo funciona debajo del capó), la cadena que representa el tipo depende de usted. A continuación, puede volver a escribir el despachador, es decir, la función deepEquals
, para ser algo así como:
var dispatchTypeEquals = {
number: function(a,b) {...a==b...},
array: function(a,b) {...deepEquals(x,y)...},
...
}
function deepEquals(a,b) {
var typeA = extractType(a);
var typeB = extractType(a);
return typeA==typeB && dispatchTypeEquals[typeA](a,b);
}
var a= [1, 2, 3, ''3''];
var b = [1, 2, 3];
var c = a.filter(function (i) { return ! ~b.indexOf(i); });
alert(c.length);