2012-06-21 62 views
22

La expresión¿Existe alguna forma idiomática de probar la igualdad de matrices en Coffeescript?

[1, 2, 3] == [1, 2, 3] 

evalúa a false en CoffeeScript pero hay una manera concisa, idiomática para probar la igualdad matriz?

+0

No sé mucho sobre coffeescript, pero parece que está probando la igualdad de los objetos con ''==' en lugar de valores de matriz individuales. –

+5

alguien debería notar aquí que '==' en coffeescript se evaua a '===' en javascript. – SirLenz0rlot

Respuesta

14

Si usted está tratando con matrices de números, y usted sabe que no hay valores nulos o valores no definidos en las matrices, se puede comparar como cadenas:

a = [1, 2, 3] 
b = [1, 2, 3] 

console.log "#{a}" is "#{b}" # true 
console.log '' + a is '' + b # true 

Nótese, sin embargo, que este se romperá tan pronto como se comienza a comparar matrices de otras cosas que no son los números:

a = [1, 2, 3] 
b = ['1,2', 3] 

console.log "#{a}" is "#{b}" # true 

Si desea una solución más robusta, que puede utilizar Array#every:

arrayEqual = (a, b) -> 
    a.length is b.length and a.every (elem, i) -> elem is b[i] 

console.log arrayEqual [1, 2, 3], [1, 2, 3] # true 
console.log arrayEqual [1, 2, 3], [1, 2, '3'] # false 
console.log arrayEqual [1, 2, 3], ['1,2', 3] # false 

Observe que primero se comparan las longitudes de las matrices para que arrayEqual [1], [1, 2, 3] no devuelva verdadero.

+2

Me gusta el Array :: cada solución pero el método IE II no es compatible con IE <9 (sí, desearía no tener que preocuparme, pero ...) –

+3

@PirateRob Sí, eso podría ser un problema. Personalmente, dejé de comentar "ten cuidado de que esto no funcione en IE" porque muchas veces no tiene sentido; hay mucho desarrollo de JS móvil, Node.js y otras cosas, entonces, sin información previa, ni siquiera comentaré sobre la compatibilidad de IE. Si necesita preocuparse por IE pero preferiría usar las cosas más nuevas de JS, puede degradar un poco la experiencia de los usuarios de IE solamente e incluir condicionalmente una "corrección", como [es5-shim] (https://github.com/kriskowal/es5-shim /), para todas esas golosinas :) – epidemian

+0

Además, podría usar la implementación de Underscore de ['every'] (http://underscorejs.org/#all), que garantizará la compatibilidad entre navegadores para un costo muy bajo :) – epidemian

6

Si no le importa introducir una dependencia Underscore.js, puede usar algunas de sus utilidades. No es masivamente elegante, pero no puedo pensar en una manera más fácil de hacerlo con CoffeeScript claro:

a = [ 1, 2, 3 ] 
b = [ 1, 2, 3 ] 
equal = a.length == b.length and _.all(_.zip(a, b), ([x,y]) -> x is y) 
+3

La única mejora que podría pensar sería usar la asignación de desestructuración de coffeescript: '_.all (x es y para [x, y] en _.zip (a, b))' – Trevor

+0

Ten cuidado con eso ['_.all'] (http://underscorejs.org/#all) _needs_ una función de iterador. Este ejemplo [rompe] (http://jsfiddle.net/W5THS/) para mí tanto en Firefox como en Chrome como está ahora ("iterator is not a function" se lanza en FF). Afortunadamente, es fácil [arreglarlo] (http://jsfiddle.net/W5THS/1/): '_.all _.zip (a, b), ([x, y]) -> x es y' :) – epidemian

+0

Desafortunadamente, usar '_.zip' hará que esta solución compare' [1, 2, 3, indefinido] 'y' [1, 2, 3] '[como igual] (http://jsfiddle.net/W5THS/2 /) :( – epidemian

3

No consideraría este idiomática pero esto sería una manera de hacerlo sin agregar una biblioteca adicional :

a = [1, 2, 3, 4] 
b = [22, 3, 4] 

areEqual = true 
maxIndex = Math.max(a.length, b.length)-1 
for i in [0..maxIndex] 
    testEqual = a[i] is b[i] 
    areEqual = areEqual and testEqual 

console.log areEqual 

Un enfoque más limpio sería el uso de la función de JavaScript reduce(). Esto es un poco más corto, pero no estoy seguro de que todos los navegadores soporten reducir.

a = [1, 3, 4, 5] 
b = [1, 3, 4, 5] 

maxIndex = Math.max(a.length, b.length)-1 
areEqual = true 
[0..maxIndex].reduce (p, c, i, ar) -> areEqual = areEqual and (a[i] is b[i]) 

console.log "areEqual=#{areEqual}" 
0

Soy un gran fan de Sugar.js. Si le sucede a estar usando lo siguiente:

a = [1, 2, 3] 
b = [1, 2, 3] 
Object.equal(a, b) 
3

La siguiente funciona muy bien y no requiere dependencias:

arrayEqual = (ar1, ar2) -> 
    JSON.stringify(ar1) is JSON.stringify(ar2) 
+0

Esto funciona muy bien para los objetos, también. –

0

Esta función devuelve true si matrices tienen la misma longitud y todos los valores con mismo índice tener el mismo valor. Lanza un error si alguno de los argumentos no es una matriz.

isArray = Array.isArray || (subject) -> 
    toString.call(subject) is '[object Array]' 

compareArrays = (a, b) -> 
    unless isArray(a) and isArray b 
     throw new Error '`arraysAreEqual` called with non-array' 

    return false if a.length isnt b.length 

    for valueInA, index in a 
     return false if b[index] isnt valueInA 

    true 
Cuestiones relacionadas