Come faccio a confrontare due dizionari in Swift?

C’è un modo semplice per confrontare due dizionari [String: AnyObject] in swift, dato che non accetta l’operatore == ?

Confrontando due dizionari, intendo controllare che abbiano le stesse chiavi esatte e che per ogni chiave abbiano gli stessi valori.

Come già accennato da Hot Licks puoi usare il metodo NSDictionary isEqualToDictionary () per verificare se sono uguali come segue:

 let dic1: [String: AnyObject] = ["key1": 100, "key2": 200] let dic2: [String: AnyObject] = ["key1": 100, "key2": 200] let dic3: [String: AnyObject] = ["key1": 100, "key2": 250] println( NSDictionary(dictionary: dic1).isEqualToDictionary(dic2) ) // true println( NSDictionary(dictionary: dic1).isEqualToDictionary(dic3) ) // false 

puoi anche implementare un operatore personalizzato “==” come segue:

 public func ==(lhs: [String: AnyObject], rhs: [String: AnyObject] ) -> Bool { return NSDictionary(dictionary: lhs).isEqualToDictionary(rhs) } println(dic1 == dic2) // true println(dic1 == dic3) // false 

Xcode 9 • Swift 4

Da docs, il dizionario è ora definito come una struttura:

 struct Dictionary : Collection, ExpressibleByDictionaryLiteral 

Descrizione

Una collezione i cui elementi sono coppie chiave-valore. Un dizionario è un tipo di tabella hash, che fornisce un accesso rapido alle voci che contiene. Ogni voce nella tabella viene identificata utilizzando la sua chiave, che è un tipo hashable come una stringa o un numero. Si utilizza quella chiave per recuperare il valore corrispondente, che può essere qualsiasi object. In altre lingue, tipi di dati simili sono noti come hash o array associati. Crea un nuovo dizionario usando un dizionario letterale. Un dizionario letterale è un elenco separato da virgole di coppie chiave-valore, in cui un colon separa ciascuna chiave dal suo valore associato, racchiusa tra parentesi quadre. È ansible assegnare un dizionario letterale a una variabile o costante o passarlo a una funzione che si aspetta un dizionario.

Ecco come crei un dizionario di codici di risposta HTTP e i relativi messaggi:

 var responseMessages = [200: "OK", 403: "Access forbidden", 404: "File not found", 500: "Internal server error"] 

La variabile responseMessages viene dedotta per il tipo [Int: String] . Il tipo di chiave del dizionario è Int e il tipo di valore del dizionario è String .

Per creare un dizionario senza coppie di valori-chiave, utilizzare un dizionario vuoto letterale ([:]).

 var emptyDict: [String: String] = [:] 

Qualsiasi tipo conforms al protocollo Hashable può essere utilizzato come tipo di chiave del dizionario, inclusi tutti i tipi di base di Swift. Puoi utilizzare i tuoi tipi personalizzati come chiavi del dizionario rendendoli conformi al protocollo Hashable.


Non è più necessario definire un operatore personalizzato:

Dai documenti:

 static func ==(lhs: [Key : Value], rhs: [Key : Value]) -> Bool 

test:

 let dic1 = ["key1": 100, "key2": 200] let dic2 = ["key1": 100, "key2": 200] let dic3 = ["key1": 100, "key2": 250] print(dic1 == dic2) // true print(dic1 == dic3) // false 

Nell’esempio sopra riportato, tutte le chiavi e i valori del dizionario sono dello stesso tipo. Se proviamo a confrontare due dizionari di tipo [String: Any] Xcode si lamenterà che l’operatore binario == non può essere applicato a due operandi [String: Any] .

  let dic4: [String: Any] = ["key1": 100, "key2": "200"] let dic5: [String: Any] = ["key1": 100, "key2": "200"] let dic6: [String: Any] = ["key1": 100, "key2": Date()] print(dic4 == dic5) // Binary operator == cannot be applied to two `[String: Any]` operands 

Ma possiamo estendere le funzionalità dell’operatore == implementando un operatore infisso, convertendo Swift Dictionary in NSDictionary e vincolando il valore del dizionario al Protocollo Hashable:


 public func ==(lhs: [K: V], rhs: [K: V] ) -> Bool { return (lhs as NSDictionary).isEqual(to: rhs) } 

test:

 let dic4: [String: AnyHashable] = ["key1": 100, "key2": "200"] let dic5: [String: AnyHashable] = ["key1": 100, "key2": "200"] let dic6: [String: AnyHashable] = ["key1": 100, "key2": Date()] 

 print(dic4 == dic5) // true print(dic4 == dic6) // false 

Aggiornamento Swift 4:

Il confronto dei dizionari ora è nativo! (Documenti qui )


Swift 3:

Leo Dabus ha già un post scritto in modo eccellente con la soluzione accettata. Tuttavia, per quanto mi riguarda, ho scoperto che era necessario un ulteriore passo per essere pienamente utilizzabile. Come puoi vedere dal suo codice, devi impostare il tuo tipo di dizionario su [AnyHashable: Any] , altrimenti otterrai l’ Binary operator '==' cannot be applied to two '[String : Any]' operands , per usare un dizionario comune nel deserializzare JSON per il mio esempio.

Generici in soccorso !:

 // Swift 3.0 func == (left: [K:V], right: [K:V]) -> Bool { return NSDictionary(dictionary: left).isEqual(to: right) } 

o in un altro caso, con [String: Any?] :

 func == (left: [K:V?], right: [K:V?]) -> Bool { guard let left = left as? [K: V], let right = right as? [K: V] else { return false } return NSDictionary(dictionary: left).isEqual(to: right) } 

In Swift 2, quando sia Key sia Value sono Equatable , puoi usare == sul dizionario stesso:

 public func ==(lhs: [Key : Value], rhs: [Key : Value]) -> Bool 

E, NSObject è equo:

 public func ==(lhs: NSObject, rhs: NSObject) -> Bool 

Nel tuo caso, se stai lavorando con oggetti Obj-C che vuoi confrontare usando isEqual: puoi semplicemente usare NSObject come tipo di valore (piuttosto che AnyObject).

Senza il tipo personalizzato di valore del dizionario, in Swift 2+ è ansible utilizzare l’operatore == per confrontare due Dictionary per verificare se sono uguali o meno.

Ma in alcuni casi con tipi personalizzati come valore del Dictionary (come struct ), è necessario adottare Equatable in modo che il tipo personalizzato utilizzi l’operatore == .

Ex:

 // custom type struct Custom: Equatable { var value: Int } // MARK: adopting Equatable func ==(lhs: Custom, rhs: Custom) -> Bool { if lhs.value == rhs.value { return true } else { return false } } 

Ora puoi usare l’operatore == per confrontare due dizionari:

 let dic3: [String: Custom] = ["key1": Custom(value:1), "key2": Custom(value:2)] let dic4: [String: Custom] = ["key1": Custom(value:1), "key2": Custom(value:2)] if (dic3 == dic4) { print("equal") } else { print("not equal") }