Me gustaría comparar dos matrices ... idealmente, de manera eficiente. Nada de lujos, solo true
si son idénticos, y false
si 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?
javascript
arrays
json
Julian H. Lam
fuente
fuente
([] == []) == false
.Respuestas:
Para comparar matrices, repítelas y compara cada valor:
Comparación de matrices:
Uso:
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:
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:
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:Hice una pequeña herramienta de prueba para ambas funciones .
Bonificación: matrices anidadas con
indexOf
ycontains
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/
fuente
this[i] !== array[i]
lugar de!=
.equals
lugar decompare
. Al menos en .NET, compare generalmente devuelve un int con signo que indica qué objeto es mayor que el otro. Ver: Comparar . Comparar .Si bien esto solo funciona para matrices escalares (vea la nota a continuación), es breve:
Rr, en ECMAScript 6 / CoffeeScript / TypeScript con funciones de flecha:
(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:
P.ej:
Entonces el código anterior daría
true
fuente
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)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í:
fuente
_.isEqual([1,2,3], [2,1,3]) => false
isEqual
funcionalidad, siempre puede usar el módulo_.isEqual([1,2,3].sort(), [2,1,3].sort()) => true
Creo que esta es la forma más sencilla de hacerlo usando JSON stringify, y puede ser la mejor solución en algunas situaciones:
Esto convierte los objetos
a1
ya2
en 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.
fuente
No está claro qué quiere decir con "idéntico". Por ejemplo, ¿las matrices
a
y lasb
siguientes son idénticas (tenga en cuenta las matrices anidadas)?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íafalse
. Funciona en el caso general, que lasjoin()
soluciones basadas en JSON y no:fuente
true
. La respuesta explica que no lo hará. Si necesita comparar matrices anidadas, puede agregar fácilmente una verificación recursiva.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
arrayCompare
procedimiento genérico que solo se refiere a recorrer los arreglos. A partir de ahí, crearemos nuestras otras funciones básicas de comparación comoarrayEqual
yarrayDeepEqual
, etc.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,
arrayCompare
toma la función de comparaciónf
, y dos matrices de entrada,xs
yys
. En su mayor parte, todo lo que hacemos es llamarf (x) (y)
a cada elemento en las matrices de entrada. Regresamos tempranofalse
si el definido por el usuariof
regresafalse
, 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
arrayCompare
función, podemos crear fácilmente otras funciones que podamos necesitar. Comenzaremos con la primariaarrayEqual
...Simple como eso.
arrayEqual
se puede definir conarrayCompare
y una función de comparación que se comparaa
con elb
uso===
(para igualdad estricta).Tenga en cuenta que también definimos
equal
como su propia función. Esto resalta el papel dearrayCompare
una 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
arrayLooseEqual
usando un==
en su lugar. Ahora, al comparar1
(Número) con'1'
(Cadena), el resultado será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
arrayCompare
procedimiento es lo suficientemente versátil como para usarlo de una manera que hace que una prueba de igualdad profunda sea muy fácil ...Simple como eso. Construimos un comparador profundo usando otra función de orden superior. Esta vez estamos envolviendo
arrayCompare
el uso de un comparador personalizado que se compruebe sia
yb
son matrices. Si es así, vuelva a aplicar laarrayDeepCompare
comparacióna
yb
al 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 usandoequal
,looseEqual
o cualquier otro comparador que hacer.Debido a que
arrayDeepCompare
es curry, también podemos aplicarlo parcialmente como lo hicimos en los ejemplos anterioresPara 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
id
valor ...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.
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
x
es mayor que cada unoy
...Menos es más
Puedes ver que en realidad estamos haciendo más con menos código. No hay nada complicado en
arrayCompare
sí 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 unRegExp
comparador! 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
arrayEqual
en 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.fuente
arrayCompare
? Sí, la función es curry, pero difiere desome
yevery
.arrayCompare
toma 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 ^ _ ^En el espíritu de la pregunta original:
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
cada (69%) por usuario2782196
reducir (74%) por DEI
unirse y toString (78%) por Gaizka Allende y vivek
half toString (90%) por Victor Palomo
stringify (100%) por radtek
fuente
Array.from({length: 1000}).map((a,v)=>
$ {v}.padStart(10,2));
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.
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:
También escribí un jsfiddle rápido con la función y este ejemplo:
http://jsfiddle.net/Roundaround/DLkxX/
fuente
Aunque esto tiene muchas respuestas, una que creo que puede ser de ayuda:
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:
Usted obtendrá
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:
Usted obtendrá
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.
fuente
En las mismas líneas que JSON.encode es usar join ().
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.
Si el orden debe permanecer igual, entonces es solo un bucle, no se necesita ningún tipo de clasificación.
fuente
.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.checkArrays([1,2,3] , ["1,2",3]) == true
y es muy poco probable que eso sea lo que quieres que suceda!join()
así lo hace sutilmente defectuoso!Aquí hay una versión mecanografiada:
Algunos casos de prueba para moca:
fuente
Si está utilizando un marco de prueba como Mocha con la biblioteca de aserción Chai , puede usar la igualdad profunda para comparar matrices.
Esto debería devolver verdadero solo si las matrices tienen elementos iguales en los índices correspondientes.
fuente
Si son solo dos matrices de números o cadenas, esta es una línea rápida
fuente
[11]
. Bastante obvio de por qué sucede esto y cómo solucionarlo.En mi caso, las matrices comparadas contienen solo números y cadenas. Esta función le mostrará si las matrices contienen los mismos elementos.
¡Probémoslo!
fuente
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.are_arrs_equal([1,2], [2,1])
vuelvetrue
como se esperaba. Quizás esta solución no sea ideal, pero funcionó para mí.are_arrs_match([1,2], ["1,2"])
(devolucionestrue
). Y tenga en cuenta que lathe sort()
llamada modificará las matrices de entrada ; esto puede no ser deseable.Esto compara 2 matrices sin clasificar:
fuente
Para una variedad de números intente:
Mostrar fragmento de código
Nota: este método no funcionará cuando la matriz también contenga cadenas, por ejemplo
a2 = [1, "2,3"]
.fuente
Podríamos hacer esto de manera funcional, usando
every
( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/every )fuente
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 ()).
fuente
Herer es mi solución:
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.
fuente
equal({}, {a:1})
yequal({}, null)
esto y errores:equal({a:2}, null)
Así es como lo hice.
fuente
Comparando 2 matrices:
función de llamada
fuente
Creo en simple
JS
y conECMAScript 2015
, que es dulce y simple de entender.Espero que ayude a alguien.
fuente
Ampliando la idea de Tomáš Zato. El Array.prototype.compare de Tomas debe de hecho llamarse Array.prototype.compareIdentical.
Transmite:
Pero falla en:
Aquí está la mejor versión (en mi opinión):
http://jsfiddle.net/igos/bcfCY/
fuente
////// OR ///////
fuente
Otro enfoque con muy poco código (usando Array reduce y Array incluye ):
Si quieres comparar también la igualdad de orden:
La
length
verificació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
.fuente
Un enfoque simple:
fuente
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
fuente
Recursivo y funciona en matrices ANIDADAS :
fuente
Funciona con MÚLTIPLES argumentos con matrices ANIDADAS :
fuente
fuente