two objetos objects elementos elemento comparar cadenas buscar array agregar javascript arrays json

objetos - compare objects javascript



¿Cómo comparar arrays en JavaScript? (30)

Me gustaría comparar dos matrices ... idealmente, eficientemente. Nada lujoso, solo true si son idénticos, y false si no. No en vano, el operador de comparación no parece funcionar.

var a1 = [1,2,3]; var a2 = [1,2,3]; console.log(a1==a2); // Returns false console.log(JSON.stringify(a1)==JSON.stringify(a2)); // Returns true

JSON codifica cada matriz, pero ¿hay una manera más rápida o "mejor" de simplemente comparar matrices sin tener que iterar a través de cada valor?


El camino practico

Creo que es incorrecto decir que una implementación en particular es "The Right Way ™" si es solo "correcto" ("correcto") en contraste con una solución "incorrecta". La solución de Tomáš es una clara mejora con respecto a la comparación de matrices basada en cadenas, pero eso no significa que sea objetivamente "correcto". ¿Qué es lo correcto de todos modos? ¿Es el más rápido? ¿Es el más flexible? ¿Es lo más fácil de comprender? ¿Es el más rápido de depurar? ¿Utiliza las menos operaciones? ¿Tiene efectos secundarios? Ninguna solución puede tener lo mejor de todas las cosas.

Tomáš podría decir que su solución es rápida, pero también diría que es innecesariamente complicada. Intenta ser una solución todo en uno que funcione para todos los arreglos, anidados o no. De hecho, incluso acepta más que simples arreglos como entrada y aún intenta dar una respuesta "válida".

Los genéricos ofrecen reutilización.

Mi respuesta abordará el problema de manera diferente. Comenzaré con un procedimiento genérico de arrayCompare que solo se ocupa de arrayCompare las matrices. A partir de ahí, construiremos nuestras otras funciones de comparación básicas como arrayEqual y arrayDeepEqual , etc.

// arrayCompare :: (a -> a -> Bool) -> [a] -> [a] -> Bool const arrayCompare = f => ([x,...xs]) => ([y,...ys]) => x === undefined && y === undefined ? true : Boolean (f (x) (y)) && arrayCompare (f) (xs) (ys)

En mi opinión, el mejor tipo de código ni siquiera necesita comentarios, y esto no es una excepción. Aquí ocurre tan poco que puede comprender el comportamiento de este procedimiento casi sin esfuerzo. Claro, parte de la sintaxis de ES6 puede parecerle extraña ahora, pero eso es solo porque ES6 es relativamente nuevo.

Como sugiere el tipo, arrayCompare toma la función de comparación, f , y dos matrices de entrada, xs y ys . En su mayor parte, todo lo que hacemos es llamar a f (x) (y) para cada elemento en las matrices de entrada. Devolvemos una false anticipada si la f definida por el usuario devuelve false , gracias a la evaluación de cortocircuito de && . Entonces, sí, esto significa que el comparador puede detener la iteración anticipada y evitar el bucle en el resto de la matriz de entrada cuando no sea necesario.

Comparación estricta

A continuación, utilizando nuestra función arrayCompare , podemos crear fácilmente otras funciones que podamos necesitar. Comenzaremos con el arrayEqual elemental ...

// equal :: a -> a -> Bool const equal = x => y => x === y // notice: triple equal // arrayEqual :: [a] -> [a] -> Bool const arrayEqual = arrayCompare (equal) const xs = [1,2,3] const ys = [1,2,3] console.log (arrayEqual (xs) (ys)) //=> true // (1 === 1) && (2 === 2) && (3 === 3) //=> true const zs = [''1'',''2'',''3''] console.log (arrayEqual (xs) (zs)) //=> false // (1 === ''1'') //=> false

Simple como eso. arrayEqual se puede definir con arrayCompare y una función de comparación que compara arrayCompare usando === (para igualdad estricta).

Note que también definimos equal como su propia función. Esto resalta el rol de arrayCompare como una función de orden superior para utilizar nuestro comparador de primer orden en el contexto de otro tipo de datos (Array).

Comparación suelta

Podríamos definir arrayLooseEqual con la misma arrayLooseEqual utilizando a == lugar. Ahora, al comparar 1 (Número) con ''1'' (Cadena), el resultado será true ...

// looseEqual :: a -> a -> Bool const looseEqual = x => y => x == y // notice: double equal // arrayLooseEqual :: [a] -> [a] -> Bool const arrayLooseEqual = arrayCompare (looseEqual) const xs = [1,2,3] const ys = [''1'',''2'',''3''] console.log (arrayLooseEqual (xs) (ys)) //=> true // (1 == ''1'') && (2 == ''2'') && (3 == ''3'') //=> true

Comparación profunda (recursiva)

Probablemente has notado que esto es solo una comparación superficial, aunque. Seguramente la solución de Tomáš es "The Right Way ™" porque hace una comparación profunda implícita, ¿verdad?

Bueno, nuestro procedimiento arrayCompare es lo suficientemente versátil como para usarlo de una manera que hace que una prueba de igualdad profunda sea una brisa ...

// isArray :: a -> Bool const isArray = Array.isArray // arrayDeepCompare :: (a -> a -> Bool) -> [a] -> [a] -> Bool const arrayDeepCompare = f => arrayCompare (a => b => isArray (a) && isArray (b) ? arrayDeepCompare (f) (a) (b) : f (a) (b)) const xs = [1,[2,[3]]] const ys = [1,[2,[''3'']]] console.log (arrayDeepCompare (equal) (xs) (ys)) //=> false // (1 === 1) && (2 === 2) && (3 === ''3'') //=> false console.log (arrayDeepCompare (looseEqual) (xs) (ys)) //=> true // (1 == 1) && (2 == 2) && (3 == ''3'') //=> true

Simple como eso. Construimos un comparador profundo utilizando otra función de orden superior. Esta vez estamos envolviendo arrayCompare usando un comparador personalizado que verificará si a y b son matrices. Si es así, arrayDeepCompare aplicar arrayDeepCompare contrario, compare a y b con el comparador especificado por el usuario ( f ). Esto nos permite mantener el comportamiento de comparación profunda separado de la forma en que realmente comparamos los elementos individuales. Es decir, como se muestra en el ejemplo anterior, podemos realizar una comparación profunda utilizando equal , looseEqual o cualquier otro comparador que hagamos.

Debido a que arrayDeepCompare está en curry, podemos aplicarlo parcialmente como lo hicimos en los ejemplos anteriores también

// arrayDeepEqual :: [a] -> [a] -> Bool const arrayDeepEqual = arrayDeepCompare (equal) // arrayDeepLooseEqual :: [a] -> [a] -> Bool const arrayDeepLooseEqual = arrayDeepCompare (looseEqual)

Para mí, esto ya es una clara mejora con respecto a la solución de Tomáš porque puedo elegir explícitamente una comparación superficial o profunda para mis arreglos, según sea necesario.

Comparación de objetos (ejemplo)

Ahora, ¿qué pasa si tienes una matriz de objetos o algo? Tal vez quiera considerar esas matrices como "iguales" si cada objeto tiene el mismo valor de id ...

// idEqual :: {id: Number} -> {id: Number} -> Bool const idEqual = x => y => x.id !== undefined && x.id === y.id // arrayIdEqual :: [a] -> [a] -> Bool const arrayIdEqual = arrayCompare (idEqual) const xs = [{id:1}, {id:2}] const ys = [{id:1}, {id:2}] console.log (arrayIdEqual (xs) (ys)) //=> true // (1 === 1) && (2 === 2) //=> true const zs = [{id:1}, {id:6}] console.log (arrayIdEqual (xs) (zs)) //=> false // (1 === 1) && (2 === 6) //=> false

Simple como eso. Aquí he usado objetos JS de vainilla, pero este tipo de comparador podría funcionar para cualquier tipo de objeto; incluso sus objetos personalizados. La solución de Tomáš tendría que ser completamente reelaborada para apoyar este tipo de prueba de igualdad

Arreglo profundo con objetos? No es un problema. Construimos funciones genéricas altamente versátiles, por lo que funcionarán en una amplia variedad de casos de uso.

const xs = [{id:1}, [{id:2}]] const ys = [{id:1}, [{id:2}]] console.log (arrayCompare (idEqual) (xs) (ys)) //=> false console.log (arrayDeepCompare (idEqual) (xs) (ys)) //=> true

Comparación arbitraria (ejemplo)

¿O qué pasaría si quisiera hacer algún otro tipo de comparación completamente arbitraria? Tal vez quiero saber si cada x es mayor que cada y ...

// gt :: Number -> Number -> Bool const gt = x => y => x > y // arrayGt :: [a] -> [a] -> Bool const arrayGt = arrayCompare (gt) const xs = [5,10,20] const ys = [2,4,8] console.log (arrayGt (xs) (ys)) //=> true // (5 > 2) && (10 > 4) && (20 > 8) //=> true const zs = [6,12,24] console.log (arrayGt (xs) (zs)) //=> false // (5 > 6) //=> false

Menos es más

Puedes ver que en realidad estamos haciendo más con menos código. No hay nada complicado en arrayCompare , y cada uno de los comparadores personalizados que hemos creado tiene una implementación muy simple.

Con facilidad, podemos definir exactamente cómo deseamos que se comparen dos arreglos: poco profundos, profundos, estrictos, sueltos, alguna propiedad del objeto, o algún cálculo arbitrario, o cualquier combinación de estos, todo con un solo procedimiento , arrayCompare . Tal vez incluso soñar con un comparador RegExp ! Sé cómo los niños aman esas expresiones regulares ...

¿Es el más rápido? No Pero probablemente tampoco necesita serlo. Si la velocidad es la única métrica utilizada para medir la calidad de nuestro código, se desechará una gran cantidad de código realmente bueno. Es por eso que llamo a este enfoque el método práctico . O tal vez para ser más justo, de una manera práctica. Esta descripción es adecuada para esta respuesta porque no estoy diciendo que esta respuesta solo sea práctica en comparación con alguna otra respuesta; es objetivamente cierto. Hemos alcanzado un alto grado de practicidad con muy poco código sobre el que es muy fácil razonar. Ningún otro código puede decir que no hemos obtenido esta descripción.

¿Eso lo convierte en la solución "correcta" para usted? Eso depende de usted para decidir. Y nadie más puede hacer eso por ti; solo tu sabes cuales son tus necesidades En casi todos los casos, valoro el código directo, práctico y versátil en vez de inteligente y rápido. Lo que usted valora puede diferir, así que elija lo que le funcione.

Editar

Mi antigua respuesta estaba más centrada en descomponer arrayEqual en pequeños procedimientos. Es un ejercicio interesante, pero no es realmente la mejor manera (más práctica) de abordar este problema. Si estás interesado, puedes ver este historial de revisiones.


A partir de la respuesta de Tomáš Zato, estoy de acuerdo en que solo recorrer las matrices es el más rápido. Además (como han dicho otros), la función debería llamarse igual / igual, no comparar. A la luz de esto, modifiqué la función para manejar la comparación de arrays en busca de similitud, es decir, tienen los mismos elementos, pero fuera de orden, para uso personal, y pensé que la pondría aquí para que todos la vean.

Array.prototype.equals = function (array, strict) { if (!array) return false; if (arguments.length == 1) strict = true; if (this.length != array.length) return false; for (var i = 0; i < this.length; i++) { if (this[i] instanceof Array && array[i] instanceof Array) { if (!this[i].equals(array[i], strict)) return false; } else if (strict && this[i] != array[i]) { return false; } else if (!strict) { return this.sort().equals(array.sort(), true); } } return true; }

Esta función toma un parámetro adicional de estricto que por defecto es verdadero. Este parámetro estricto define si las matrices deben ser totalmente iguales tanto en el contenido como en el orden de esos contenidos, o simplemente contener el mismo contenido.

Ejemplo:

var arr1 = [1, 2, 3, 4]; var arr2 = [2, 1, 4, 3]; // Loosely equal to 1 var arr3 = [2, 2, 3, 4]; // Not equal to 1 var arr4 = [1, 2, 3, 4]; // Strictly equal to 1 arr1.equals(arr2); // false arr1.equals(arr2, false); // true arr1.equals(arr3); // false arr1.equals(arr3, false); // false arr1.equals(arr4); // true arr1.equals(arr4, false); // true

También he escrito un jsfiddle rápido con la función y este ejemplo:
http://jsfiddle.net/Roundaround/DLkxX/


Creo que esta es la forma más sencilla de hacerlo utilizando JSON stringify, y puede ser la mejor solución en algunas situaciones:

JSON.stringify(a1) === JSON.stringify(a2);

Esto convierte los objetos a1 y a2 en cadenas para que puedan compararse. El orden es importante en la mayoría de los casos, ya que puede ordenar el objeto utilizando un algoritmo de clasificación que se muestra en una de las respuestas anteriores.

Tenga en cuenta que ya no está comparando el objeto sino la representación de cadena del objeto. Puede que no sea exactamente lo que quieres.


En el espíritu de la pregunta original:

Me gustaría comparar dos matrices ... idealmente, eficientemente . Nada lujoso , solo verdadero si son idénticos, y falso si no.

He estado ejecutando pruebas de rendimiento en algunas de las sugerencias más simples que se proponen aquí con los siguientes results (rápido a lento):

while (67%) por Tim Down

var i = a1.length; while (i--) { if (a1[i] !== a2[i]) return false; } return true

every (69%) por usuario2782196

a1.every((v,i)=> v === a2[i]);

reduce (74%) por DEIs

a1.reduce((a, b) => a && a2.includes(b), true);

join & toString (78%) por Gaizka Allende & vivek

a1.join('''') === a2.join(''''); a1.toString() === a2.toString();

Media toString (90%) por Victor Palomo

a1 == a2.toString();

stringify (100%) por Radtek

JSON.stringify(a1) === JSON.stringify(a2);

Tenga en cuenta que los ejemplos a continuación asumen que las matrices son ordenadas, matrices unidimensionales. .length comparación de .length se ha eliminado para un punto de referencia común (agregue a1.length === a2.length a cualquiera de las sugerencias y obtendrá un aumento de rendimiento de ~ 10%). Elija las soluciones que más le convengan, sabiendo la velocidad y la limitación de cada una.

Nota no relacionada: es interesante ver a las personas que tienen a John Waynes feliz con los disparadores en el botón de voto negativo en respuestas perfectamente legítimas a esta pregunta.


En las mismas líneas que JSON.encode es usar join ().

function checkArrays( arrA, arrB ){ //check if lengths are different if(arrA.length !== arrB.length) return false; //slice so we do not effect the original //sort makes sure they are in order //join makes it a string so we can do a string compare var cA = arrA.slice().sort().join(","); var cB = arrB.slice().sort().join(","); return cA===cB; } var a = [1,2,3,4,5]; var b = [5,4,3,2,1]; var c = [1,2,3,4]; var d = [1,2,3,4,6]; var e = ["1","2","3","4","5"]; //will return true console.log( checkArrays(a,b) ); //true console.log( checkArrays(a,c) ); //false console.log( checkArrays(a,d) ); //false console.log( checkArrays(a,e) ); //true

El único problema es si le importan los tipos que la última comparación prueba. Si te interesan los tipos, tendrás que hacer un bucle.

function checkArrays( arrA, arrB ){ //check if lengths are different if(arrA.length !== arrB.length) return false; //slice so we do not effect the orginal //sort makes sure they are in order var cA = arrA.slice().sort(); var cB = arrB.slice().sort(); for(var i=0;i<cA.length;i++){ if(cA[i]!==cB[i]) return false; } return true; } var a = [1,2,3,4,5]; var b = [5,4,3,2,1]; var c = [1,2,3,4]; var d = [1,2,3,4,6]; var e = ["1","2","3","4","5"]; console.log( checkArrays(a,b) ); //true console.log( checkArrays(a,c) ); //false console.log( checkArrays(a,d) ); //false console.log( checkArrays(a,e) ); //false

Si el orden debe seguir siendo el mismo, de lo que es solo un bucle, no se necesita ningún ordenamiento.

function checkArrays( arrA, arrB ){ //check if lengths are different if(arrA.length !== arrB.length) return false; for(var i=0;i<arrA.length;i++){ if(arrA[i]!==arrB[i]) return false; } return true; } var a = [1,2,3,4,5]; var b = [5,4,3,2,1]; var c = [1,2,3,4]; var d = [1,2,3,4,6]; var e = ["1","2","3","4","5"]; console.log( checkArrays(a,a) ); //true console.log( checkArrays(a,b) ); //false console.log( checkArrays(a,c) ); //false console.log( checkArrays(a,d) ); //false console.log( checkArrays(a,e) ); //false


Me gusta usar la biblioteca Underscore para proyectos de codificación pesada de matriz / objeto ... en Underscore y Lodash, si estás comparando matrices u objetos, se ve así:

_.isEqual(array1, array2) // returns a boolean _.isEqual(object1, object2) // returns a boolean


No está claro qué quiere decir con "idéntico". Por ejemplo, ¿son las matrices a y b inferiores idénticas (tenga en cuenta las matrices anidadas)?

var a = ["foo", ["bar"]], b = ["foo", ["bar"]];

Aquí hay una función de comparación de matrices optimizada que compara los elementos correspondientes de cada matriz a su vez utilizando una igualdad estricta y no hace una comparación recursiva de los elementos de la matriz que son matrices, lo que significa que para el ejemplo anterior, arraysIdentical(a, b) devolvería false Funciona en el caso general, en el que las soluciones basadas en JSON y join() no:

function arraysIdentical(a, b) { var i = a.length; if (i != b.length) return false; while (i--) { if (a[i] !== b[i]) return false; } return true; };


Para comparar matrices, recorrelas y compara cada valor:

Comparando matrices:

// Warn if overriding existing method if(Array.prototype.equals) console.warn("Overriding existing Array.prototype.equals. Possible causes: New API defines the method, there''s a framework conflict or you''ve got double inclusions in your code."); // attach the .equals method to Array''s prototype to call it on any array Array.prototype.equals = function (array) { // if the other array is a falsy value, return if (!array) return false; // compare lengths - can save a lot of time if (this.length != array.length) return false; for (var i = 0, l=this.length; i < l; i++) { // Check if we have nested arrays if (this[i] instanceof Array && array[i] instanceof Array) { // recurse into the nested arrays if (!this[i].equals(array[i])) return false; } else if (this[i] != array[i]) { // Warning - two different object instances will never be equal: {x:20} != {x:20} return false; } } return true; } // Hide method from for-in loops Object.defineProperty(Array.prototype, "equals", {enumerable: false});

Uso:

[1, 2, [3, 4]].equals([1, 2, [3, 2]]) === false; [1, "2,3"].equals([1, 2, 3]) === false; [1, 2, [3, 4]].equals([1, 2, [3, 4]]) === true; [1, 2, 1, 2].equals([1, 2, 1, 2]) === true;

Puede decir " Pero es mucho más rápido comparar cadenas, no hay bucles ... " bueno, entonces debe tener en cuenta que existen bucles. Primer bucle recursivo que convierte Array en cadena y segundo, que compara dos cadenas. Así que este método es más rápido que el uso de la cadena .

Creo que siempre se deben almacenar grandes cantidades de datos en arreglos, no en objetos. Sin embargo, si utiliza objetos, también se pueden comparar parcialmente.
Así es cómo:

Comparando objetos:

He dicho anteriormente, que dos instancias de objetos nunca serán iguales, incluso si contienen los mismos datos en este momento:

({a:1, foo:"bar", numberOfTheBeast: 666}) == ({a:1, foo:"bar", numberOfTheBeast: 666}) //false

Esto tiene una razón, ya que puede haber, por ejemplo, variables privadas dentro de los objetos.

Sin embargo, si solo usa la estructura de objetos para contener datos, la comparación es todavía posible:

Object.prototype.equals = function(object2) { //For the first loop, we only check for types for (propName in this) { //Check for inherited methods and properties - like .equals itself //https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty //Return false if the return value is different if (this.hasOwnProperty(propName) != object2.hasOwnProperty(propName)) { return false; } //Check instance type else if (typeof this[propName] != typeof object2[propName]) { //Different types => not equal return false; } } //Now a deeper check using other objects property names for(propName in object2) { //We must check instances anyway, there may be a property that only exists in object2 //I wonder, if remembering the checked values from the first loop would be faster or not if (this.hasOwnProperty(propName) != object2.hasOwnProperty(propName)) { return false; } else if (typeof this[propName] != typeof object2[propName]) { return false; } //If the property is inherited, do not check any more (it must be equa if both objects inherit it) if(!this.hasOwnProperty(propName)) continue; //Now the detail check and recursion //This returns the script back to the array comparing /**REQUIRES Array.equals**/ if (this[propName] instanceof Array && object2[propName] instanceof Array) { // recurse into the nested arrays if (!this[propName].equals(object2[propName])) return false; } else if (this[propName] instanceof Object && object2[propName] instanceof Object) { // recurse into another objects //console.log("Recursing to compare ", this[propName],"with",object2[propName], " both named /""+propName+"/""); if (!this[propName].equals(object2[propName])) return false; } //Normal value comparison for strings and numbers else if(this[propName] != object2[propName]) { return false; } } //If everything passed, let''s say YES return true; }

Sin embargo, recuerde que éste sirve para comparar datos como JSON, no instancias de clase y otras cosas. Si quieres comparar más objetos complicados, mira esta respuesta y es una función superlong .
Para que esto funcione con Array.equals , debe editar un poco la función original:

... // Check if we have nested arrays if (this[i] instanceof Array && array[i] instanceof Array) { // recurse into the nested arrays if (!this[i].equals(array[i])) return false; } /**REQUIRES OBJECT COMPARE**/ else if (this[i] instanceof Object && array[i] instanceof Object) { // recurse into another objects //console.log("Recursing to compare ", this[propName],"with",object2[propName], " both named /""+propName+"/""); if (!this[i].equals(array[i])) return false; } else if (this[i] != array[i]) { ...

Hice una pequeña herramienta de prueba para ambas funciones .

Bonificación: Matrices anidadas con indexOf y contains

Samy Bencherif ha preparado funciones útiles para el caso en el que está buscando un objeto específico en matrices anidadas, que están disponibles aquí: https://jsfiddle.net/SamyBencherif/8352y6yw/


Si bien esto solo funciona para matrices escalares (vea la nota a continuación), es breve:

array1.length === array2.length && array1.every(function(value, index) { return value === array2[index]})

Rr, en ECMAScript 6 / CoffeeScript / TypeScript con funciones de flecha:

array1.length === array2.length && array1.every((value, index) => value === array2[index])

(Nota: ''escalar'' aquí significa valores que se pueden comparar directamente usando === . Entonces: números, cadenas, objetos por referencia, funciones por referencia. Consulte la referencia de MDN para obtener más información sobre los operadores de comparación).

ACTUALIZAR

Por lo que leí de los comentarios, ordenar la matriz y comparar puede dar un resultado preciso:

array1.length === array2.length && array1.sort().every(function(value, index) { return value === array2.sort()[index]});

P.ej:

array1 = [2,3,1,4]; array2 = [1,2,3,4];

Entonces el código anterior daría true


Si son dos matrices de números o cadenas solamente, esta es una rápida de una línea

const array1 = [1, 2, 3]; const array2 = [1, 3, 4]; console.log(array1.join('','') === array2.join('','')) //false const array3 = [1, 2, 3]; const array4 = [1, 2, 3]; console.log(array3.join('','') === array4.join('','')) //true


A pesar de que esto tiene muchas respuestas, una que creo que es de ayuda:

const newArray = [ ...new Set( [...arr1, ...arr2] ) ]

No se indica en la pregunta cómo se verá la estructura de la matriz, por lo que si está seguro de que no tendrá matrices anidadas ni objetos en su matriz (me pasó a mí, por eso llegué a esto). respuesta) el código anterior funcionará.

Lo que sucede es que usamos el operador de difusión (...) para concentrar ambas matrices, luego usamos Set para eliminar cualquier duplicado. Una vez que tengas eso, puedes comparar sus tamaños, si las tres matrices tienen el mismo tamaño, puedes irte.

Esta respuesta también ignora el orden de los elementos , como dije, la situación exacta me sucedió, así que tal vez alguien en la misma situación podría terminar aquí (como lo hice).

Edit1.

Respondiendo a la pregunta de Dmitry Grinko: "¿Por qué usaste el operador de propagación (...) aquí - ... ¿nuevo conjunto? No funciona"

Considere este código:

const arr1 = [ ''a'', ''b'' ] const arr2 = [ ''a'', ''b'', ''c'' ] const newArray = [ new Set( [...arr1, ...arr2] ) ] console.log(newArray)

Obtendrás

[ Set { ''a'', ''b'', ''c'' } ]

Para trabajar con ese valor, necesitaría usar algunas propiedades del conjunto (consulte https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set ). Por otro lado, cuando usas este código:

const arr1 = [ ''a'', ''b'' ] const arr2 = [ ''a'', ''b'', ''c'' ] const newArray = [ ...new Set( [...arr1, ...arr2] ) ] console.log(newArray)

Obtendrás

[ ''a'', ''b'', ''c'' ]

Esa es la diferencia, el primero me daría un Set, también funcionaría, ya que podría obtener el tamaño de ese Set, pero el último me da el array que necesito, lo que es más directo a la resolución.


Aquí hay una versión de CoffeeScript, para aquellos que prefieren eso:

Array.prototype.equals = (array) -> return false if not array # if the other array is a falsy value, return return false if @length isnt array.length # compare lengths - can save a lot of time for item, index in @ if item instanceof Array and array[index] instanceof Array # Check if we have nested arrays if not item.equals(array[index]) # recurse into the nested arrays return false else if this[index] != array[index] return false # Warning - two different object instances will never be equal: {x:20} != {x:20} true

Todos los créditos van a @ tomas-zato.


Aquí hay una versión de Typescript:

//https://.com/a/16436975/2589276 export function arraysEqual<T>(a: Array<T>, b: Array<T>): boolean { if (a === b) return true if (a == null || b == null) return false if (a.length != b.length) return false for (var i = 0; i < a.length; ++i) { if (a[i] !== b[i]) return false } return true } //https://.com/a/16436975/2589276 export function arraysDeepEqual<T>(a: Array<T>, b: Array<T>): boolean { return JSON.stringify(a) === JSON.stringify(b) }

Algunos casos de prueba para moca:

it(''arraysEqual'', function () { let a = [1,2] let b = [1,2] let c = [2,3] let d = [2, 3] let e = [''car'',''apple'',''banana''] let f = [''car'',''apple'',''banana''] let g = [''car'',''apple'',''banan8''] expect(arraysEqual(a, b)).to.equal(true) expect(arraysEqual(c, d)).to.equal(true) expect(arraysEqual(a, d)).to.equal(false) expect(arraysEqual(e, f)).to.equal(true) expect(arraysEqual(f, g)).to.equal(false) }) it(''arraysDeepEqual'', function () { let a = [1,2] let b = [1,2] let c = [2,3] let d = [2, 3] let e = [''car'',''apple'',''banana''] let f = [''car'',''apple'',''banana''] let g = [''car'',''apple'',''banan8''] let h = [[1,2],''apple'',''banan8''] let i = [[1,2],''apple'',''banan8''] let j = [[1,3],''apple'',''banan8''] expect(arraysDeepEqual(a, b)).to.equal(true) expect(arraysDeepEqual(c, d)).to.equal(true) expect(arraysDeepEqual(a, d)).to.equal(false) expect(arraysDeepEqual(e, f)).to.equal(true) expect(arraysDeepEqual(f, g)).to.equal(false) expect(arraysDeepEqual(h, i)).to.equal(true) expect(arraysDeepEqual(h, j)).to.equal(false) })


Comparando 2 matrices:

var arr1 = [1,2,3]; var arr2 = [1,2,3]; function compare(arr1,arr2) { if((arr1 == arr2) && (arr1.length == arr2.length)) return true; else return false; }

función de llamada

var isBool = compare(arr1.sort().join(),arr2.sort().join());


Elija cada uno de [a] y recorra todo de [b]: Resultado: 1, 5

var a = [1,4,5,9]; var b = [1,6,7,5]; for (i = 0; i < a.length; i++) { for (z = 0; z < a.length; z++) { if (a[i] === b[z]) { console.log(b[z]); // if match > console.log it } } }


Esta función compara dos matrices de forma arbitraria y dimesionalidad:

function equals(a1, a2) { if (!Array.isArray(a1) || !Array.isArray(a2)) { throw new Error("Arguments to function equals(a1, a2) must be arrays."); } if (a1.length !== a2.length) { return false; } for (var i=0; i<a1.length; i++) { if (Array.isArray(a1[i]) && Array.isArray(a2[i])) { if (equals(a1[i], a2[i])) { continue; } else { return false; } } else { if (a1[i] !== a2[i]) { return false; } } } return true; }


Esto compara 2 matrices sin clasificar:

function areEqual(a, b) { if ( a.length != b.length) { return false; } return a.filter(function(i) { return !b.includes(i); }).length === 0; }


Herer es mi solución:

/** * Tests two data structures for equality * @param {object} x * @param {object} y * @returns {boolean} */ var equal = function(x, y) { if (typeof x !== typeof y) return false; if (x instanceof Array && y instanceof Array && x.length !== y.length) return false; if (typeof x === ''object'') { for (var p in x) if (x.hasOwnProperty(p)) { if (typeof x[p] === ''function'' && typeof y[p] === ''function'') continue; if (x[p] instanceof Array && y[p] instanceof Array && x[p].length !== y[p].length) return false; if (typeof x[p] !== typeof y[p]) return false; if (typeof x[p] === ''object'' && typeof y[p] === ''object'') { if (!equal(x[p], y[p])) return false; } else if (x[p] !== y[p]) return false; } } else return x === y; return true; };

Funciona con cualquier estructura de datos anidada, y obviamente ignora los métodos de los objetos. Ni siquiera piense en extender Object.prototype con este método, cuando lo intenté una vez, jQuery se rompió;)

Para la mayoría de los arreglos, sigue siendo más rápido que la mayoría de las soluciones de serialización. Probablemente sea el método de comparación más rápido para matrices de registros de objetos.



Si la matriz es simple y el orden es importante, estas dos líneas pueden ayudar

//Assume var a = [''a'',''b'', ''c'']; var b = [''a'',''e'', ''c'']; if(a.length !== b.length) return false; return !a.reduce( function(prev,next,idx, arr){ return prev || next != b[idx] },false );

Reduce los recorridos a través de uno de los matrices y devuelve ''falso'' si al menos un elemento de ''a'' no es igual al elemento de ''b'' Solo envuelve esto en función


esta secuencia de comandos compara objetos, matrices y matrices multidimensionales

function compare(a,b){ var primitive=[''string'',''number'',''boolean'']; if(primitive.indexOf(typeof a)!==-1 && primitive.indexOf(typeof a)===primitive.indexOf(typeof b))return a===b; if(typeof a!==typeof b || a.length!==b.length)return false; for(i in a){ if(!compare(a[i],b[i]))return false; } return true; }

La primera línea comprueba si es un tipo primitivo. Si es así, compara los dos parámetros.

Si son objetos. itera sobre el Objeto y verifica cada elemento recursivamente.

Uso:

var a=[1,2,[1,2]]; var b=[1,2,[1,2]]; var isEqual=compare(a,b); //true


para una matriz de una sola dimensión simplemente puede usar:

arr1.sort().toString() == arr2.sort().toString()

Esto también se hará cargo de la matriz con el índice no coincidente.


En mi caso, los arreglos comparados contienen solo números y cadenas. Esta función le mostrará si los arreglos contienen los mismos elementos.

function are_arrs_match(arr1, arr2){ return arr1.sort().toString() === arr2.sort().toString() }

¡Vamos a probarlo!

arr1 = [1, 2, 3, ''nik''] arr2 = [''nik'', 3, 1, 2] arr3 = [1, 2, 5] console.log (are_arrs_match(arr1, arr2)) //true console.log (are_arrs_match(arr1, arr3)) //false


Extendiendo la idea de Tomáš Zato. Array.prototype.compare de Tomas debe ser de hecho llamado Array.prototype.compareIdentical.

Se pasa sobre

[1, 2, [3, 4]].compareIdentical ([1, 2, [3, 2]]) === false; [1, "2,3"].compareIdentical ([1, 2, 3]) === false; [1, 2, [3, 4]].compareIdentical ([1, 2, [3, 4]]) === true; [1, 2, 1, 2].compareIdentical ([1, 2, 1, 2]) === true;

Pero falla en:

[[1, 2, [3, 2]],1, 2, [3, 2]].compareIdentical([1, 2, [3, 2],[1, 2, [3, 2]]])

Aquí está la versión mejor (en mi opinión):

Array.prototype.compare = function (array) { // if the other array is a falsy value, return if (!array) return false; // compare lengths - can save a lot of time if (this.length != array.length) return false; this.sort(); array.sort(); for (var i = 0; i < this.length; i++) { // Check if we have nested arrays if (this[i] instanceof Array && array[i] instanceof Array) { // recurse into the nested arrays if (!this[i].compare(array[i])) return false; } else if (this[i] != array[i]) { // Warning - two different object instances will never be equal: {x:20} != {x:20} return false; } } return true; }

http://jsfiddle.net/igos/bcfCY/


Mi solución compara objetos, no matrices. Esto funcionaría de la misma manera que Tomáš, ya que las matrices son objetos, pero sin la advertencia:

Object.prototype.compare_to = function(comparable){ // Is the value being compared an object if(comparable instanceof Object){ // Count the amount of properties in @comparable var count_of_comparable = 0; for(p in comparable) count_of_comparable++; // Loop through all the properties in @this for(property in this){ // Decrements once for every property in @this count_of_comparable--; // Prevents an infinite loop if(property != "compare_to"){ // Is the property in @comparable if(property in comparable){ // Is the property also an Object if(this[property] instanceof Object){ // Compare the properties if yes if(!(this[property].compare_to(comparable[property]))){ // Return false if the Object properties don''t match return false; } // Are the values unequal } else if(this[property] !== comparable[property]){ // Return false if they are unequal return false; } } else { // Return false if the property is not in the object being compared return false; } } } } else { // Return false if the value is anything other than an object return false; } // Return true if their are as many properties in the comparable object as @this return count_of_comparable == 0; }

Espero que esto te ayude a ti oa alguien más en busca de una respuesta.


Podríamos hacer esto de manera funcional, usando every( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/every )

function compareArrays(array1, array2) { if (array1.length === array2.length) return array1.every((a, index) => a === array2[index]) else return false } // test var a1 = [1,2,3]; var a2 = [1,2,3]; var a3 = [''a'', ''r'', ''r'', ''a'', ''y'', ''1''] var a4 = [''a'', ''r'', ''r'', ''a'', ''y'', ''2''] console.log(compareArrays(a1,a2)) // true console.log(compareArrays(a1,a3)) // false console.log(compareArrays(a3,a4)) // false


Si está utilizando un marco de prueba como Mocha con la biblioteca de aserciones de Chai , puede usar deep igualdad deep para comparar arrays.

expect(a1).to.deep.equal(a2)

Esto debería devolver verdadero solo si las matrices tienen elementos iguales en los índices correspondientes.


JSON.stringify(collectionNames).includes(JSON.stringify(sourceNames)) ? array.push(collection[i]) : null

Así es como lo hice.


function compareArrays(arrayA, arrayB) { if (arrayA.length != arrayB.length) return true; for (i = 0; i < arrayA.length; i++) if (arrayB.indexOf(arrayA[i]) == -1) { return true; } } for (i = 0; i < arrayB.length; i++) { if (arrayA.indexOf(arrayB[i]) == -1) { return true; } } return false; }


var a1 = [1,2,3,6]; var a2 = [1,2,3,5]; function check(a, b) { return (a.length != b.length) ? false : a.every(function(row, index) { return a[index] == b[index]; }); } check(a1, a2);

////// O ///////

var a1 = [1,2,3,6]; var a2 = [1,2,3,6]; function check(a, b) { return (a.length != b.length) ? false : !(a.some(function(row, index) { return a[index] != b[index]; })); } check(a1, a2)