2012-06-21 16 views
22

L'espressioneEsiste un modo idiomatico per testare l'uguaglianza dell'array in Coffeescript?

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

viene valutato come false in CoffeeScript ma c'è un modo idiomatica conciso per testare l'uguaglianza array?

+0

Non conosco molto il coffeescript, ma sembra che si stia verificando l'uguaglianza degli oggetti con '==' invece dei singoli valori di matrice. –

+5

qualcuno dovrebbe notare che '==' in coffeescript viene evaporato in '===' in javascript. – SirLenz0rlot

risposta

14

Se avete a che fare con le matrici di numeri, e si sa che non ci sono nulli o valori non definiti nel vostro array, è possibile confrontare come stringhe:

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

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

noti, tuttavia, che questo si romperà, non appena si inizia a matrici di confronto di altre cose che non sono numeri:

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

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

Se si desidera una soluzione più robusta, è possibile utilizzare 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 

Si noti che per prima cosa si confrontano le lunghezze degli array in modo che arrayEqual [1], [1, 2, 3] non restituisca true.

+2

Mi piace l'array :: ogni soluzione ma IIRC quel metodo non è supportato in IE <9 (si, vorrei non doverlo importare, ma ...) –

+3

@PirateRob Sì, potrebbe essere un problema. Personalmente ho smesso di commentare "attenti che questo potrebbe non funzionare in IE" perché molte volte non ha senso; c'è un sacco di sviluppo JS mobile, Node.js e quant'altro, quindi, senza informazioni precedenti non ho nemmeno commenti sulla compatibilità IE. Se dovresti preoccuparti di IE, ma preferiresti comunque usare le cose JS più recenti, puoi degradare un po 'l'esperienza degli utenti di IE e includere condizionalmente uno "shim", come [es5-shim] (https://github.com)/kriskowal/es5-shim /), per tutte quelle prelibate :) – epidemian

+0

Inoltre, è possibile utilizzare l'implementazione di Underscore di ['every'] (http://underscorejs.org/#all), che garantirà la compatibilità cross-browser per un costo molto basso :) – epidemian

6

Se non ti interessa introdurre una dipendenza Underscore.js, potresti utilizzare alcune delle sue utilità. Non è massicciamente elegante, ma non riesco a pensare a un modo più semplice per farlo con CoffeeScript pianura:

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

Unico miglioramento che potrei pensare sarebbe quello di usare l'assegnazione destrutturante del coffeescript: '_.all (x è y per [x, y] in _.zip (a, b))' – Trevor

+0

Attenzione che ['_.all'] (http://underscorejs.org/#all) _needs_ una funzione iteratore. Questo esempio [pause] (http://jsfiddle.net/W5THS/) per me sia in Firefox che in Chrome come è ora ("l'iteratore non è una funzione" è lanciato in FF). Fortunatamente, è facile [aggiustarlo] (http://jsfiddle.net/W5THS/1/): '_.all _.zip (a, b), ([x, y]) -> x è y' :) – epidemian

+0

Sfortunatamente, l'uso di '_.zip' farà sì che questa soluzione confronti' [1, 2, 3, undefined] 'e' [1, 2, 3] '[uguale] (http://jsfiddle.net/W5THS/2 /) :( – epidemian

3

non vorrei prendere in considerazione questa idiomatica, ma questo sarebbe un modo di farlo senza l'aggiunta di una libreria in più :

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 approccio più pulito sarebbe utilizzando la funzione di JavaScript reduce(). Questo è un po 'più breve, ma non sono sicuro che tutti i browser supportino la riduzione.

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

Sono un grande fan di Sugar.js. Se vi capita di essere utilizzando tale:

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

Il seguente funziona alla grande e non richiede dipendenze:

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

Questo funziona perfettamente anche per gli oggetti. –

0

Questa funzione restituisce true se gli array hanno stessa lunghezza e tutti i valori con lo stesso indice di avere lo stesso valore. Genera un errore se uno degli argomenti non è un array.

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 
Problemi correlati