swift - premios - joe alwyn
¿Cómo comparo dos diccionarios en Swift? (4)
Actualización de Swift 4:
¡Comparar diccionarios ahora es nativo! (Documentos here )
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 ser completamente utilizable.
Como puede ver en su código, debe establecer 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 == <K, V>(left: [K:V], right: [K:V]) -> Bool {
return NSDictionary(dictionary: left).isEqual(to: right)
}
o en otro caso que tuve, con
[String: Any?]
:
func == <K, V>(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)
}
¿Hay una manera fácil de comparar dos diccionarios
[String: AnyObject]
en forma rápida, 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 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 "==" como sigue:
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
De los documentos, el diccionario ahora se define como una estructura:
struct Dictionary<Key : Hashable, Value> : 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 hashable, 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. Cree un nuevo diccionario utilizando un diccionario literal. Un diccionario literal es una lista separada por comas de pares clave-valor, en la que los dos puntos separan cada clave de su valor asociado, rodeados 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"]
Se infiere que la variable responseMessages tiene el tipo
[Int: String]
. El tipo de clave del diccionario esInt
y el tipo de valor del diccionario esString
.
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 tipo de clave de un diccionario, incluidos todos los tipos básicos de Swift. Puede usar sus propios tipos personalizados como claves de diccionario haciéndolos cumplir con el 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, transfiriendo Swift Dictionary a NSDictionary y restringiendo el valor del diccionario a Hashable Protocol:
public func ==<K, V: Hashable>(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
En Swift 2, cuando
tanto
Key
como
Value
son
Equatable
, puede usar
==
en el diccionario:
public func ==<Key : Equatable, Value : Equatable>(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 usando
isEqual:
simplemente puede usar NSObject como su tipo de valor (en lugar de AnyObject).
Sin el tipo personalizado en el valor de Diccionario, en Swift 2+ puede usar el operador
==
para comparar dos
Dictionary
para verificar 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")
}