¿Cómo comparo dos diccionarios en Swift?

¿Existe una manera fácil de comparar dos diccionarios [String: AnyObject] en swift, ya que no acepta el operador == ?

Al comparar dos diccionarios, me refiero a comprobar que tienen las mismas claves exactas y para cada clave tienen los mismos valores.

Como ya lo mencionó Hot Licks, puede usar el método NSDictionary isEqualToDictionary () para verificar si son iguales de la siguiente manera:

 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 

también puede implementar un operador personalizado “==” de la siguiente manera:

 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

Desde los documentos, el diccionario ahora se define como una estructura:

 struct Dictionary : Collection, ExpressibleByDictionaryLiteral 

Descripción

Una colección cuyos elementos son pares clave-valor. Un diccionario es un tipo de tabla hash que proporciona acceso rápido a las entradas que contiene. Cada entrada en la tabla se identifica usando su clave, que es un tipo que se puede cargar, como una cadena o un número. Utiliza esa clave para recuperar el valor correspondiente, que puede ser cualquier objeto. En otros idiomas, los tipos de datos similares se conocen como hashes o matrices asociadas. Crea un nuevo diccionario usando un literal de diccionario. Un literal de diccionario es una lista de pares de valores-clave separados por comas, en la que dos puntos separan cada clave de su valor asociado, rodeada de corchetes. Puede asignar un literal de diccionario a una variable o constante o pasarlo a una función que espera un diccionario.

Así es como crearía un diccionario de códigos de respuesta HTTP y sus mensajes relacionados:

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

La variable responseMessages se deduce que tiene el tipo [Int: String] . El tipo de clave del diccionario es Int , y el tipo de valor del diccionario es String .

Para crear un diccionario sin pares clave-valor, use un literal de diccionario vacío ([:]).

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

Cualquier tipo que se ajuste al protocolo Hashable se puede usar como un tipo de clave de diccionario, incluidos todos los tipos básicos de Swift. Puede usar sus propios tipos personalizados como claves de diccionario al hacer que se ajusten al protocolo Hashable.


Ya no necesitamos definir un operador personalizado:

De los documentos:

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

Pruebas:

 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 

En el ejemplo anterior, todas las claves y valores del diccionario son del mismo tipo. Si intentamos comparar dos diccionarios de tipo [String: Any] Xcode se quejará de que el operador binario == no se puede aplicar a dos operandos [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 

Pero podemos ampliar la funcionalidad del operador == implementando un operador infijo, convirtiendo Swift Dictionary en NSDictionary y restringiendo el valor del diccionario a Hashable Protocol:


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

Pruebas:

 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 

Swift 4 Actualización:

¡Comparar diccionarios ahora es nativo! (Documentos aquí )


Swift 3:

Leo Dabus ya tiene una publicación excelentemente escrita con la solución aceptada. Sin embargo, para mí, descubrí que necesitaba un paso más para poder usarlo por completo. Como puede ver en su código, debe configurar su tipo de diccionario en [AnyHashable: Any] , o de lo contrario obtendrá el Binary operator '==' cannot be applied to two '[String : Any]' operands , para usar un diccionario común en la deserialización de JSON para mi ejemplo.

¡Genéricos al rescate !:

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

o en otro caso tuve, 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) } 

En Swift 2, cuando tanto la Key como el Value son Equatable , puede usar == en el diccionario mismo:

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

Y, NSObject es Equatable:

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

En su caso, si está trabajando con objetos Obj-C que desea comparar con isEqual: simplemente puede usar NSObject como su tipo de valor (en lugar de AnyObject).

Sin un tipo personalizado en el valor de Dictionary, en Swift 2+ puede usar el operador == para comparar dos Dictionary y comprobar si son iguales o no.

Pero en algunos casos con tipos personalizados como el valor del Dictionary (como struct ), debe adoptar Equatable para que ese tipo personalizado use el operador == .

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 } } 

Ahora puede usar el operador == para comparar dos diccionarios:

 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") }