2015-03-12 21 views
30

Mentre lavora attraverso la Scala exercises on Iterables, ho incontrato il seguente strano comportamento:Imposta Scala contengono gli stessi elementi, ma sameElements() restituisce falso

val xs = Set(5,4,3,2,1) 
val ys = Set(1,2,3,4,5) 
xs sameElements ys  // true 

val xs = Set(3,2,1) 
val ys = Set(1,2,3) 
xs sameElements ys  // false - WAT?! 

Sicuramente questi set sono gli stessi elementi, e dovrebbe ignorare l'ordinazione; e perché funziona come previsto solo per il set più grande?

+0

Utilizzare '==' per verificare l'uguaglianza indipendentemente dall'ordine e dalle ripetizioni. –

+0

Questo è un buon punto per confrontare 'Set's l'uno con l'altro, anche se ho appena notato che' Elenco (1,2,3) == Vettore (1,2,3) 'ma' Elenco (1,2,3) ! = Set (1,2,3) 'e' List (1,2,3)! = Array (1,2,3) 'che è un altro potenziale campo minato! – DNA

+0

E come sottolinea Paul Draper nei commenti sottostanti, 'Array (1,2,3)! = Array (1,2,3)' !! – DNA

risposta

57

La libreria di raccolte Scala fornisce implementazioni specializzate per Set di meno di 5 valori (vedere source). Gli iteratori per queste implementazioni restituiscono gli elementi nell'ordine in cui sono stati aggiunti, anziché l'ordinamento coerente basato su hash utilizzato per i set più grandi.

Inoltre, sameElements (scaladoc) è definita su Iterable s (è implementato in IterableLike - vedi source); restituisce true solo se gli iteratori restituiscono gli stessi elementi nello stesso ordine.

Quindi, anche se Set(1,2,3) e Set(3,2,1)dovrebbe essere equivalenti, i loro iteratori sono diversi, quindi sameElements restituisce false.

Questo comportamento è sorprendente, e probabilmente un bug poiché viola le aspettative matematiche per un Set (ma solo per alcune dimensioni di Set!).

Come da I.K. sottolinea nei commenti, == funziona bene se si stanno solo confrontando i set tra loro, ovvero Set(1,2,3) == Set(3,2,1). Tuttavia, sameElements è più generale in quanto può confrontare gli elementi di due iterabili. Ad esempio, List(1, 2, 3) == Array(1, 2, 3) è falso, ma List(1, 2, 3) sameElements Array(1, 2, 3) è true.

Più in generale, l'uguaglianza può essere fonte di confusione - notare che:

List(1,2,3) == Vector(1,2,3) 
List(1,2,3) != Set(1,2,3) 
List(1,2,3) != Array(1,2,3)  
Array(1,2,3) != Array(1,2,3) 

ho submitted a fix per il Scala exercises che spiega il problema sameElements.

+0

Con il nome del metodo, mi aspetto che ignori l'ordine indipendentemente dal tipo di raccolta. Per esempio. Mi aspetterei che 'List (1,2,3) sameElements List (3,2,1)' valuti a 'true', perché entrambi contengono gli stessi elementi_. Se l'ordine conta, qual è la differenza prevista tra 'sameElements' e' == '? –

+2

Grande scoperta ... In un grande progetto qualcosa del genere può far impazzire chiunque. Hai sollevato un biglietto per questo nei numeri ufficiali scala. –

+1

Amo lo scala così tanto ma i bug di questo tipo sono così scoraggianti. Buona scoperta –