¿Cómo comparar matrices en JavaScript?


991

Me gustaría comparar dos matrices ... idealmente, de manera eficiente. Nada de lujos, solo truesi son idénticos, y falsesi no. No es sorprendente que el operador de comparación no parezca 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

La codificación JSON de cada matriz sí, pero ¿existe una forma más rápida o "mejor" de comparar simplemente las matrices sin tener que recorrer cada valor?


55
Primero puede comparar su longitud y, si son iguales, cada valor.
TJHeuvel

56
¿Qué hace que dos matrices sean iguales para ti? ¿Los mismos elementos? ¿El mismo orden de elementos? La codificación como JSON solo funciona siempre que el elemento de la matriz se pueda serializar a JSON. Si la matriz puede contener objetos, ¿qué tan profundo irías? ¿Cuándo son dos objetos "iguales"?
Felix Kling

48
@FelixKling, definir "igualdad" es definitivamente un tema sutil, pero para las personas que llegan a JavaScript desde lenguajes de nivel superior, no hay excusas para tonterías ([] == []) == false.
Alex D

44
@AlexD parece que las matrices usan igualdad de referencia, que es lo que esperarías. Sería bastante horrible si no pudieras hacer eso
JonnyRaa

3
@AlexD No puedo pensar en un lenguaje en el que esto no suceda. En C ++, estaría comparando dos punteros: falso. En Java, estás haciendo lo mismo que en JavaScript. En PHP, algo detrás de escena recorrerá las matrices: ¿llama a PHP un lenguaje de nivel superior?
Tomáš Zato - Restablece a Monica el

Respuestas:


877

Para comparar matrices, repítelas y compara cada valor:

Comparación de 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, sin bucles ... " bueno, entonces debe tener en cuenta que HAY bucles. Primer bucle recursivo que convierte Array en cadena y segundo, que compara dos cadenas. Entonces, este método es más rápido que el uso de una cadena .

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

Comparación de 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 objeto para contener datos, la comparación aún es 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 este es para comparar JSON como datos, no instancias de clase y otras cosas. Si desea comparar objetos más complicados, mire esta respuesta y su función es muy larga .
Para que esto funcione 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 indexOfycontains

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


27
Si desea hacer comparaciones estrictas, use en this[i] !== array[i]lugar de !=.
Tim S.

38
Su método debe llamarse en equalslugar de compare. Al menos en .NET, compare generalmente devuelve un int con signo que indica qué objeto es mayor que el otro. Ver: Comparar . Comparar .
Oliver

15
No solo es esta la forma correcta de hacerlo, también es considerablemente más eficiente. Aquí hay una secuencia de comandos jsperf rápida que preparé para todos los métodos sugeridos en esta pregunta. jsperf.com/comparing-arrays2
Tolga E

96
Cambiar el prototipo de un tipo incorporado definitivamente no es la forma correcta
Jasper

31
Además, no se trata de si es fácil de reescribir, se trata del hecho de que una respuesta no debería recomendar algo que se considera una mala práctica ( developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/… ) y debería definitivamente no haga esto debajo del encabezado "La forma correcta"
Jasper

386

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


19
Me gusta esto, aunque los lectores deben tener en cuenta que esto solo funciona en matrices ordenadas.
Ellen Spertus

13
Funciona en cualquier tipo de matrices, ordenadas o no @espertus
Michał Miszczyszyn

36
Sí exactamente. Se supone que esta función compara dos matrices, no importa si están ordenadas o no, sus elementos consecutivos tienen que ser iguales.
Michał Miszczyszyn

22
@espertus De hecho, no devolverá verdadero si los elementos no tienen exactamente el mismo orden en ambas matrices. Sin embargo, el objetivo de una verificación de igualdad no es verificar si contienen los mismos elementos, sino verificar si tienen el mismo elemento en los mismos órdenes.
Quentin Roy

77
Si desea verificar si ambas matrices son iguales, contienen los mismos elementos sin clasificar (pero no se usan varias veces), puede usar a1.length==a2.length && a1.every((v,i)=>a2.includes(v)): var a1 =[1,2,3], a2 = [3,2,1];( var a1 =[1,3,3], a2 = [1,1,3];no funcionará como se esperaba)
mems

208

Me gusta usar la biblioteca Underscore para proyectos de codificación pesada de matriz / objeto ... en Underscore y Lodash, ya sea que esté comparando matrices u objetos, simplemente se ve así:

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

22
Tenga en cuenta que el orden importa _.isEqual([1,2,3], [2,1,3]) => false
Vitaliy Alekask

3
o si solo desea la isEqualfuncionalidad, siempre puede usar el módulo
lodash.isequal

66
Tal vez pueda usar _.difference (); si el orden no le importa
Ronan Quillevere

55
Podemos ordenar la matriz antes de esta verificación si el orden no importa_.isEqual([1,2,3].sort(), [2,1,3].sort()) => true
Filype

respuesta más concisa y directa en mi humilde opinión :-)
Kieran Ryan

121

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

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

Esto convierte los objetos a1y a2en cadenas para que puedan ser comparados. 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.


buena respuesta pero ¿por qué [] == [] devuelve falso? ambos son objetos simples, entonces ¿por qué?
Pardeep Jain

44
@PardeepJain, esto se debe a que, de manera predeterminada, el operador de igualdad en ECMAScript for Objects devuelve verdadero cuando hacen referencia a la misma ubicación de memoria. Pruebe var x = y = []; // ahora la igualdad devuelve verdadero.
radtek

77
solo para notar que la función JSON stringify no es rápida. Utilizado con matrices más grandes definitivamente introducirá retraso.
Lukas Liesis

66
La pregunta específicamente pregunta si hay una manera mejor / más rápida que usar JSON.stringify.
Don Hatch

Entra en más detalles sobre por qué esta puede ser una buena solución para algunas situaciones.
radtek

61

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

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

Aquí hay una función de comparación de matriz 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 en sí mismos, lo que significa que para el ejemplo anterior, arraysIdentical(a, b)volvería false. Funciona en el caso general, que las join()soluciones basadas en JSON y 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;
};

@ASDF: No queda claro a partir de la pregunta qué significa "idéntico". Obviamente, esta respuesta solo hace una comprobación superficial. Agregaré una nota.
Tim Down

esto falla para arraysIdentical ([1, 2, [3, 2]], [1, 2, [3, 2]]);
Gopinath Shiva

44
@GopinathShiva: Bueno, solo falla si esperas que regrese true. La respuesta explica que no lo hará. Si necesita comparar matrices anidadas, puede agregar fácilmente una verificación recursiva.
Tim Down

59

La manera práctica

Creo que es incorrecto decir que una implementación particular es "The Right Way ™" si solo es "correcta" ("correcta") en contraste con una solución "incorrecta". La solución de Tomáš es una mejora clara sobre la comparación de matriz basada en cadenas, pero eso no significa que sea objetivamente "correcta". ¿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 operaciones menos? ¿Tiene efectos secundarios? Ninguna solución puede tener la 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 algo más que matrices 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 arrayCompareprocedimiento genérico que solo se refiere a recorrer los arreglos. A partir de ahí, crearemos nuestras otras funciones básicas de comparación como arrayEqualy 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í sucede tan poco que puede comprender el comportamiento de este procedimiento sin casi ningún 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, arrayComparetoma la función de comparación f, y dos matrices de entrada, xsy ys. En su mayor parte, todo lo que hacemos es llamar f (x) (y)a cada elemento en las matrices de entrada. Regresamos temprano falsesi el definido por el usuario fregresa false, gracias a &&la evaluación de cortocircuito. Entonces sí, esto significa que el comparador puede detener la iteración temprano y evitar que se repita el resto del conjunto de entrada cuando sea innecesario.


Comparación estricta

Luego, usando nuestra arrayComparefunción, podemos crear fácilmente otras funciones que podamos necesitar. Comenzaremos con la primaria arrayEqual...

// 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. arrayEqualse puede definir con arrayComparey una función de comparación que se compara acon el buso ===(para igualdad estricta).

Tenga en cuenta que también definimos equalcomo su propia función. Esto resalta el papel de arrayCompareuna función de orden superior para utilizar nuestro comparador de primer orden en el contexto de otro tipo de datos (matriz).


Comparación suelta

Podríamos definirlo fácilmente arrayLooseEqualusando un ==en su 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 hayas notado que esto es solo una comparación superficial. Seguramente la solución de Tomáš es "The Right Way ™" porque hace una comparación profunda implícita, ¿verdad?

Bueno, nuestro arrayCompareprocedimiento es lo suficientemente versátil como para usarlo de una manera que hace que una prueba de igualdad profunda sea muy fácil ...

// 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 usando otra función de orden superior. Esta vez estamos envolviendo arrayCompareel uso de un comparador personalizado que se compruebe si ay bson matrices. Si es así, vuelva a aplicar la arrayDeepComparecomparación ay bal comparador especificado por el usuario ( f). Esto nos permite mantener el comportamiento de comparación profunda separado de cómo realmente comparamos los elementos individuales. Es decir, como muestra el ejemplo anterior, podemos comparar profunda usando equal, looseEqualo cualquier otro comparador que hacer.

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

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

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

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


Comparación de objetos (ejemplo)

¿Y qué pasa si tienes una variedad de objetos o algo? Tal vez desee considerar esas matrices como "iguales" si cada objeto tiene el mismo idvalor ...

// 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 vanilla JS, pero este tipo de comparador podría funcionar para cualquier tipo de objeto; incluso tus objetos personalizados. La solución de Tomáš necesitaría ser completamente revisada para soportar este tipo de prueba de igualdad

¿Matriz profunda con objetos? No es un problema. Creamos funciones genéricas y muy versátiles para que funcionen 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 quisieras hacer algún otro tipo de comparación completamente arbitraria? Tal vez quiero saber si cada uno xes mayor que cada uno 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 arrayComparesí mismo y cada uno de los comparadores personalizados que hemos creado tiene una implementación muy simple.

Con facilidad, podemos definir exactamente cómo deseamos para dos matrices que deben compararse - superficial, profundo, estricta, suelto, algunos propiedad de objeto, o algún cálculo arbitrario, o cualquier combinación de éstos - todo ello utilizando un procedimiento , arrayCompare. ¡Quizás hasta sueñe con un RegExpcomparador! Sé cómo los niños aman esas expresiones regulares ...

¿Es el más rápido? No Pero probablemente tampoco sea necesario. 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 excelente. Es por eso que llamo a este enfoque The Practical Way . O tal vez para ser más justos, una forma práctica. Esta descripción es adecuada para esta respuesta porque no digo 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 cual es muy fácil razonar. Ningún otro código puede decir que no nos hemos ganado esta descripción.

¿Eso lo convierte en la solución "adecuada" para usted? Eso depende de ti para decidir. Y nadie más puede hacer eso por ti; solo tú sabes cuáles 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 valoras puede diferir, así que elige lo que funcione para ti.


Editar

Mi vieja respuesta estaba más centrada en descomponerse arrayEqualen pequeños procedimientos. Es un ejercicio interesante, pero en realidad no es la mejor (más práctica) forma de abordar este problema. Si está interesado, puede ver este historial de revisiones.


8
"el mejor tipo de código ni siquiera necesita comentarios" ... odio decirlo, pero este código podría usar más un comentario y / o un nombre diferente: "comparar" es bastante vago. Si estoy leyendo correctamente, su "comparar" es esencialmente un cursivo recursivo "cada". Yo creo que. ¿O es un curioso "recursivo"? Hmm Esto requiere más pensamiento del necesario. Quizás un nombre mejor sería "arraysEquivalent", aprovechando la terminología estándar de "relación de equivalencia". O, incluso más claro (para mí de todos modos), "recursivamente equivalente".
Don Hatch

1
@DonHatch gracias por la oportunidad de responder. ¿Por "comparar" quieres decir arrayCompare? Sí, la función es curry, pero difiere de somey every. arrayComparetoma un comparador y dos matrices para comparar. Elegí un nombre específicamente genérico porque podemos comparar matrices usando cualquier función arbitraria. La función está programada para que pueda especializarse para crear nuevas funciones de comparación de matriz (por ejemplo, arrayEqual). ¿Me puede sugerir un nombre mejor? ¿Qué áreas cree que necesitan comentarios o explicaciones adicionales? Estoy feliz de discutir ^ _ ^
Gracias

1
No estoy seguro de si mi punto aún está claro, pero mi punto es que su función no está destinada a tomar una función arbitraria , no creo, está destinada a tomar una relación de equivalencia y devuelve una relación de equivalencia. Eso es importante: no haría nada sensato (no creo) si se le diera algún otro tipo de función binaria arbitraria como las que mencioné, incluso las que la gente suele llamar "comparar". Así que creo que sería útil poner "equivalente" en el nombre en lugar de "comparar".
Don Hatch

1
@ftor, autor: respuesta súper útil, buen trabajo, +1. Comentarios: Usted aboga por la simplicidad, pero de ninguna manera una expresión con tres flechas en una línea es simple o fácil de entender para muchos desarrolladores. Por ejemplo: f => ([x, ... xs]) => ([y, ... ys]) =>. Constantemente uso esto y todavía tenía que descomponerlo mentalmente, en lugar de "solo mirarlo". El segundo punto es correcto, use todos. Incluso sopesando sus razones, a fin de cuentas, me parece mejor no solo a mí, sino también desde su perspectiva cuando intenta inferir su filosofía de diseño.
whitneyland

1
Entiendo que este es un lugar para aprender, pero supongo que el programador promedio que estudia el estilo funcional puede transformar cualquier función curry en una no curry. Mi respuesta no sugiere que este estilo esté destinado a ser utilizado en su propio programa: escríbalo sin complicaciones, escríbalo usando sus propias reglas de sangría, escríbalo como quiera; escribo mis respuestas en un estilo que creo expresa el programa mejor. También me gusta invitar a otros a desafiar la forma en que expresamos nuestros programas sintácticamente
Gracias,

54

En el espíritu de la pregunta original:

Me gustaría comparar dos matrices ... idealmente, de manera eficiente . Nada de lujos , solo cierto si son idénticos, y falso si no.

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

mientras que (67%) por Tim Down

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

cada (69%) por usuario2782196

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

reducir (74%) por DEI

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

unirse y toString (78%) por Gaizka Allende y vivek

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

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

half 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. .lengthse ha eliminado la comparación para un punto de referencia común (agregue a1.length === a2.lengtha cualquiera de las sugerencias y obtendrá un aumento del rendimiento del ~ 10%). Elija las soluciones que funcionen mejor para usted conociendo la velocidad y la limitación de cada una.

Nota no relacionada: es interesante ver a las personas obtener a John Waynes con un gatillo feliz en el botón de votación hacia abajo sobre respuestas perfectamente legítimas a esta pregunta.


El enlace abre una prueba vacía.
Alexander Abakumov

Si aumenta el tamaño de la matriz, estos números no se aplican (especialmente el enfoque de reducción). Pruebe con Array.from({length: 1000}).map((a,v)=> $ {v}.padStart(10,2));
Narayon

solo funciona para una matriz poco profunda
Ramesh Rajendran

28

A partir de la respuesta de Tomáš Zato, estoy de acuerdo en que simplemente iterar a través de los arreglos es lo más rápido. Además (como ya han dicho otros), la función debe llamarse igual / igual, no comparar. A la luz de esto, modifiqué la función para manejar comparaciones de matrices por similitud, es decir, tienen los mismos elementos, pero fuera de orden, para uso personal, y pensé en ponerla 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 si simplemente contienen los mismos contenidos.

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 escribí un jsfiddle rápido con la función y este ejemplo:
http://jsfiddle.net/Roundaround/DLkxX/


12

Aunque esto tiene muchas respuestas, una que creo que puede ser de ayuda:

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

No se indica en la pregunta cómo se verá la estructura de la matriz, así que si sabes con seguridad que no tendrás matrices anidadas ni objetos en tu matriz (me sucedió a mí, es por eso que llegué a esto respuesta) el código anterior funcionará.

Lo que sucede es que usamos el operador spread (...) para concatenar ambas matrices, luego usamos Set para eliminar cualquier duplicado. Una vez que tenga eso, puede comparar sus tamaños, si las tres matrices tienen el mismo tamaño, está listo.

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


Editar1.

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

Considera este código:

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

Usted obtendrá

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

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

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

Usted obtendrá

[ '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 segundo me da la matriz que necesito, lo que es más directo a la resolución.


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

Dmitry Grinko Creo que respondí tu pregunta en mi Edit1. Pero no estoy seguro de lo que quisiste decir con "no funciona", ya que ambas respuestas pueden meterte en el camino
Jeferson Euclides

10

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 prueba la última comparación. 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 permanecer igual, entonces es solo un bucle, no se necesita ningún tipo de clasificación.

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

3
Esto solo funciona para ciertas matrices, y será muy lento con matrices grandes.
Tomáš Zato - Restablece a Mónica el

2
La generación de JSON también se repite, simplemente (o parece) no lo sabes. Además del bucle, generar JSON también requiere más memoria: crea 2 representaciones de cadena de dichos arreglos antes de comparar. La función downwote se implementa para ordenar las respuestas de mejor a peor. Creo que su respuesta no es una buena respuesta, así que la rechacé.
Tomáš Zato - Restablece a Monica el

2
Lo siento, acabo de decir JSON en lugar de .join(). Tal vez si declarara su segunda solución como primaria (ya que es la mejor, aunque sin dientes contra las matrices multidimensionales), no lo juzgaría de esa manera. Hasta ahora, bajé todas las respuestas que convierten las matrices en cadenas. Además, voté por todos los que usan de la manera correcta, en caso de que lo necesite para saberlo. Esto significa la respuesta de @Tim Down y la de Bireys.
Tomáš Zato - Restablece a Mónica el

66
La primera versión FALLA: ¡ checkArrays([1,2,3] , ["1,2",3]) == truey es muy poco probable que eso sea lo que quieres que suceda!
Doin

2
@epascarello: Sí, puede pero (aparte de la ineficiencia del separador muy largo que sugiere) significa que habrá casos extremos (donde la matriz contiene una cadena con su separador) donde la función checkArrays () se comporta mal . Esto podría no ser un problema si sabe algo sobre el contenido de las matrices (por lo que puede elegir un separador que seguramente no estará en los elementos de la matriz), pero si está tratando de escribir una comparación de matriz general función, entonces usarlo join()así lo hace sutilmente defectuoso!
Doin

7

Aquí hay una versión mecanografiada:

//https://stackoverflow.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://stackoverflow.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)
})

6

Si está utilizando un marco de prueba como Mocha con la biblioteca de aserción Chai , puede usar la igualdad profunda para comparar matrices.

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

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


6

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

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

const array1 = [1]; const array2 = [1, 1]; console.log (array1.join ('') === array2.join ('')) // devuelve verdadero
Dan M.

no debería: array1.join ('') es '1' y array2.join ('') es '11'
Gaizka Allende

disculpa error. La primera matriz debería ser [11]. Bastante obvio de por qué sucede esto y cómo solucionarlo.
Dan M.

No estoy seguro de qué se trata, es bastante simple: [1] .join () es "1" y [1,1] .join () es "1,1", por lo que nunca serán iguales
Gaizka Allende

por favor, lea mi comentario nuevamente con más cuidado. Si aún no lo ve, tome un botín en ideone.com/KFu427
Dan M.

5

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

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

¡Probémoslo!

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

La pregunta no le pide que ordene, por lo que su solución es incorrecta para ejemplos como are_arrs_equal([1,2], [2,1]). Además, vea otras discusiones en esta página para saber por qué la secuencia de cadenas es innecesaria, frágil e incorrecta.
trata bien tus modificaciones el

are_arrs_equal([1,2], [2,1])vuelve truecomo se esperaba. Quizás esta solución no sea ideal, pero funcionó para mí.
yesnik

Ese es precisamente el problema, esos dos no son iguales en ningún sentido sensato de la palabra "igual" para una estructura de datos ordenada . Son conjuntos, no conjuntos, y si desea establecer la igualdad, debe llamarlo así y responder una pregunta diferente. :-)
trata bien tus modificaciones el

1
Estoy de acuerdo con los comentarios anteriores, pero esta solución también funciona para mí en mis simples matrices de enteros, donde el orden no es importante, por lo que lo usaré.
tomazahlin

1
Falla para are_arrs_match([1,2], ["1,2"])(devoluciones true). Y tenga en cuenta que la the sort()llamada modificará las matrices de entrada ; esto puede no ser deseable.
try-catch-finally

5

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;  
}

Aunque es costoso (en términos de recursos de cómputo), esta es una solución sólida que debería ser buena para varios tipos, ¡y no depende de la clasificación!
usuario3.1415927


4

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

4

Su código no manejará el caso adecuadamente cuando ambas matrices tengan los mismos elementos pero no en el mismo orden.

Eche un vistazo a mi código con su ejemplo que compara dos matrices cuyos elementos son números, puede modificarlo o extenderlo para otros tipos de elementos (utilizando .join () en lugar de .toString ()).

var a1 = [1,2,3];
var a2 = [1,2,3];
const arraysAreEqual = a1.sort().toString()==a2.sort().toString();
// true if both arrays have same elements else false
console.log(arraysAreEqual);


3

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 anidados, y obviamente ignora los métodos de los objetos. Ni siquiera piense en extender Object.prototype con este método, cuando intenté esto 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. Es probablemente el método de comparación más rápido para matrices de registros de objetos.


¡no es bueno! estos dan verdad: equal({}, {a:1})y equal({}, null)esto y errores:equal({a:2}, null)
kristianlm

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

Así es como lo hice.


Buena solución, pero me pregunto en ciertas situaciones si no siempre funcionará según lo previsto, como con ciertas primitivas o matrices profundamente anidadas. Sin embargo, espero que funcione en todas las circunstancias
Ben Rondeau

3

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());

Esta respuesta no funcionará, ya que === no se comporta como se esperaba para las matrices.
Michael Yang

La respuesta funciona, aunque === no tiene ningún significado aquí (ya que sort () funciona solo en una matriz). Incluso == también funcionará.
Amay Kulkarni

Pruébalo tú mismo; se imprime falso si ejecuta este código. Esto se debe a la comparación de los valores de referencia de las matrices por ambos == y === en lugar de sus valores reales. Los == y === están destinados solo para la comparación de tipos primitivos.
Michael Yang

Devuelve verdadero, lo hemos usado, pero he eliminado '===' ahora ya que no es necesario
Amay Kulkarni

Ah, no noté que estabas convirtiendo a una cadena y llamando a la función después de ordenar y unir; mis disculpas.
Michael Yang

3

Creo en simple JSy con ECMAScript 2015, que es dulce y simple de entender.

var is_arrays_compare_similar = function (array1, array2) {

    let flag = true;

    if (array1.length == array2.length) {

        // check first array1 object is available in array2 index
        array1.every( array_obj => {
            if (flag) {
                if (!array2.includes(array_obj)) {
                    flag = false;
                }
            }
        });

        // then vice versa check array2 object is available in array1 index
        array2.every( array_obj => {
            if (flag) {
                if (!array1.includes(array_obj)) {
                    flag = false;
                }
            }
        });

        return flag;
    } else {
        return false;
    }

}

Espero que ayude a alguien.


1
¿Por qué es necesario el control viceversa? Sabemos que las matrices son del mismo tamaño, por lo que si todos los elementos de la matriz1 también se encuentran en la matriz2; ¿por qué entonces tendríamos que verificar que todos los elementos en array2 también estén en array1?
JeffryHouser

2

Ampliando la idea de Tomáš Zato. El Array.prototype.compare de Tomas debe de hecho llamarse Array.prototype.compareIdentical.

Transmite:

[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 mejor versión (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/


2
-1. Si 'falla' en el ejemplo que ha dado, entonces ese es solo el caso para una definición algo arbitraria de 'falla'. ¿Por qué esperarías que esas dos matrices diferentes se consideren iguales? Ni siquiera ha explicado qué concepto de 'igualdad' está tratando de implementar aquí, o por qué es razonable o útil, pero parece que desea comparar matrices multidimensionales como si estuvieran colapsadas a unidimensional unos. Si es así, ni siquiera lo lograste: [1,2] .compare ([[1,2]]) da falso con tu versión, al igual que con Tomáš.
Mark Amery

Basado en lo que podría inferir, él dice que [1, 2, 3, 4] y [1, 3, 2, 4] deben compararse como iguales (el orden no importa).
Gautham Badhrinathan

2
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);

////// OR ///////

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)

También puede realizar alguna función que no se iterará por completo si satisfacemos la condición requerida, como se
indicó

2

Otro enfoque con muy poco código (usando Array reduce y Array incluye ):

arr1.length == arr2.length && arr1.reduce((a, b) => a && arr2.includes(b), true)

Si quieres comparar también la igualdad de orden:

arr1.length == arr2.length && arr1.reduce((a, b, i) => a && arr2[i], true)
  • La lengthverificación asegura que el conjunto de elementos en una matriz no sea solo un subconjunto de la otra.

  • El reductor se utiliza para recorrer una matriz y buscar cada elemento en otra matriz. Si no se encuentra un elemento, la función de reducción regresa false.

    1. En el primer ejemplo, se está probando que un elemento está incluido
    2. El segundo ejemplo verifica también el pedido

1
¿Podría explicar un poco su código para aclarar esta respuesta?
ted

1. compare las longitudes de la matriz para asegurarse de que una matriz no sea un subconjunto de la otra
DEls

2. use el reductor para recorrer una matriz y buscar cada elemento en otra matriz. Si no se encuentra un elemento, la función de reducción devuelve 'falso'
DEls

@DEls: editó su explicación en la respuesta (ligeramente redactada y extendida). Ahora puede eliminar sus comentarios y marcar el primer comentario y este como obsoleto.
try-catch-finally

2

Un enfoque simple:

function equals(a, b) {
    if ((a && !b) || (!a && b) || (!a && !b) || (a.length !== b.length)) {
        return false;
    }

    var isDifferent = a.some(function (element, index) { 
        return element !== b[index];
    });

    return !isDifferent;
}

2

Ya hay algunas respuestas geniales, pero me gustaría compartir otra idea que ha demostrado ser confiable para comparar matrices. Podemos comparar dos matrices usando JSON.stringify () . Creará una cadena fuera de la matriz y, por lo tanto, comparará dos cadenas obtenidas de dos matrices para la igualdad

JSON.stringify([1,{a:1},2]) == JSON.stringify([1,{a:1},2]) //true

JSON.stringify([1,{a:1},2]) == JSON.stringify([1,{a:2},2]) //false

JSON.stringify([1,{a:1},2]) == JSON.stringify([1,{a:2},[3,4],2]) //false

JSON.stringify([1,{a:1},[3,4],2]) == JSON.stringify([1,{a:2},[3,4],2]) //false

JSON.stringify([1,{a:2},[3,4],2]) == JSON.stringify([1,{a:2},[3,4],2]) //true

JSON.stringify([1,{a:2},[3,4],2]) == JSON.stringify([1,{a:2},[3,4,[5]],2]) //false

JSON.stringify([1,{a:2},[3,4,[4]],2]) == JSON.stringify([1,{a:2},[3,4,[5]],2]) //false

JSON.stringify([1,{a:2},[3,4,[5]],2]) == JSON.stringify([1,{a:2},[3,4,[5]],2]) //true

2

Recursivo y funciona en matrices ANIDADAS :

function ArrEQ(a1,a2){
   return( 
        //:Are both elements arrays?
        Array.isArray(a1)&&Array.isArray(a2) 
        ?
        //:Yes: Test each entry for equality:
        a1.every((v,i)=>(ArrEQ(v,a2[i])))
        :
        //:No: Simple Comparison:
        (a1===a2)
   );;
};;

console.log( "Works With Nested Arrays:" );
console.log( ArrEQ( 
    [1,2,3,[4,5,[6,"SAME/IDENTICAL"]]],
    [1,2,3,[4,5,[6,"SAME/IDENTICAL"]]]
));;     
console.log( ArrEQ( 
    [1,2,3,[4,5,[6,"DIFFERENT:APPLES" ]]],
    [1,2,3,[4,5,[6,"DIFFERENT:ORANGES"]]]
));;  

2

Funciona con MÚLTIPLES argumentos con matrices ANIDADAS :

//:Return true if all of the arrays equal.
//:Works with nested arrays.
function AllArrEQ(...arrays){
    for(var i = 0; i < (arrays.length-1); i++ ){
        var a1 = arrays[i+0];
        var a2 = arrays[i+1];
        var res =( 
            //:Are both elements arrays?
            Array.isArray(a1)&&Array.isArray(a2) 
            ?
            //:Yes: Compare Each Sub-Array:
            //:v==a1[i]
            a1.every((v,i)=>(AllArrEQ(v,a2[i])))
            :
            //:No: Simple Comparison:
            (a1===a2)
        );;
        if(!res){return false;}
    };;
    return( true );
};;

console.log( AllArrEQ( 
        [1,2,3,[4,5,[6,"ALL_EQUAL"   ]]],
        [1,2,3,[4,5,[6,"ALL_EQUAL"   ]]],
        [1,2,3,[4,5,[6,"ALL_EQUAL"   ]]],
        [1,2,3,[4,5,[6,"ALL_EQUAL"   ]]],
));; 

2
In a simple way uning stringify but at same time thinking in complex arrays:

**Simple arrays**:  
var a = [1,2,3,4];  
var b = [4,2,1,4];  
JSON.stringify(a.sort()) === JSON.stringify(b.sort()) // true  

**Complex arrays**:  
var a = [{id:5,name:'as'},{id:2,name:'bes'}];  
var b = [{id:2,name:'bes'},{id:5,name:'as'}];  
JSON.stringify(a.sort(function(a,b) {return a.id - b.id})) === JSON.stringify(b.sort(function(a,b) {return a.id - b.id})) // true  

**Or we can create a sort function**  

function sortX(a,b) {  
return a.id -b.id; //change for the necessary rules  
}  
JSON.stringify(a.sort(sortX)) === JSON.stringify(b.sort(sortX)) // true  
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.