I have two dictionaries that work as text attributes of type [String: Any]
and in order to toggle ON or OFF the desired attributes I need to check if two dictionaries are the same.
I tried the following:
let current = inputTextView.typingAttributes
let undo = current.elementsEqual(attributes, by: { (arg0, arg1) -> Bool in
return ((arg0.key == arg1.key) && (arg0.value == arg1.value))
})
But on the second evaluation I get the error:
Binary operator '==' cannot be applied to two 'Any' operands
What's the best approach here to compare two dictionaries of type [String: Any]
??
Thank you
Without custom type in value of Dictionary, in Swift 2+ you can use the == operator to compare two Dictionary to check if they are equal or not. But in some cases with custom types as the Dictionary 's value (like struct ), you must adopt Equatable in order for that custom type to use == operator.
Instances of your SharedDictionary will be passed-by-reference (not copied).
dictionary in Swift is used to store elements. Dictionary also contains one key while storing elements to it, later on, we can use these keys to access the elements store in the dictionary. Dictionary in swift does not maintain the insertion order of the element in which they are stored, they are unordered in nature.
func areEqual (_ left: Any, _ right: Any) -> Bool {
if type(of: left) == type(of: right) &&
String(describing: left) == String(describing: right) { return true }
if let left = left as? [Any], let right = right as? [Any] { return left == right }
if let left = left as? [AnyHashable: Any], let right = right as? [AnyHashable: Any] { return left == right }
return false
}
extension Array where Element: Any {
static func != (left: [Element], right: [Element]) -> Bool { return !(left == right) }
static func == (left: [Element], right: [Element]) -> Bool {
if left.count != right.count { return false }
var right = right
loop: for leftValue in left {
for (rightIndex, rightValue) in right.enumerated() where areEqual(leftValue, rightValue) {
right.remove(at: rightIndex)
continue loop
}
return false
}
return true
}
}
extension Dictionary where Value: Any {
static func != (left: [Key : Value], right: [Key : Value]) -> Bool { return !(left == right) }
static func == (left: [Key : Value], right: [Key : Value]) -> Bool {
if left.count != right.count { return false }
for element in left {
guard let rightValue = right[element.key],
areEqual(rightValue, element.value) else { return false }
}
return true
}
}
let comparisonResult = ["key1": 1, 2: "Value2"] == ["key1": ["key2":2]] // false
print("!!!! \(comparisonResult)")
func test(dict1: [AnyHashable : Any], dict2: [AnyHashable : Any]) {
print("========================")
print("dict1: \(dict1)")
print("dict2: \(dict2)")
print("are\(dict1 == dict2 ? " " : " not ")equal")
}
test(dict1: ["key1": 1, 2: "Value2"],
dict2: ["key1": 1, 2: "Value2"])
test(dict1: ["key1": 1, 2: "Value2"],
dict2: ["key1": 1])
test(dict1: [2: "Value2"],
dict2: ["key1": 1])
test(dict1: ["1": 1],
dict2: [1: 1])
test(dict1: [1: 2],
dict2: [1: 3])
test(dict1: ["key1": [1,2,3,4]],
dict2: ["key1": [1,2,3,4]])
test(dict1: ["key1": [1,2,3,4]],
dict2: ["key1": [2,1,3,4]])
test(dict1: ["key1": [1,2,3,4]],
dict2: ["key1": [2,1,3]])
test(dict1: ["key1": [1,2,3,4]],
dict2: ["key1": [1,2,3,"4"]])
test(dict1: ["key1": ["key2":2]],
dict2: ["key1": ["key2":2]])
test(dict1: ["key1": ["key2":2]],
dict2: ["key1": ["key2":3]])
test(dict1: ["key1": ["key2":2]],
dict2: ["key1": ["key2":3]])
========================
dict1: [AnyHashable("key1"): 1, AnyHashable(2): "Value2"]
dict2: [AnyHashable("key1"): 1, AnyHashable(2): "Value2"]
are equal
========================
dict1: [AnyHashable("key1"): 1, AnyHashable(2): "Value2"]
dict2: [AnyHashable("key1"): 1]
are not equal
========================
dict1: [AnyHashable(2): "Value2"]
dict2: [AnyHashable("key1"): 1]
are not equal
========================
dict1: [AnyHashable("1"): 1]
dict2: [AnyHashable(1): 1]
are not equal
========================
dict1: [AnyHashable(1): 2]
dict2: [AnyHashable(1): 3]
are not equal
========================
dict1: [AnyHashable("key1"): [1, 2, 3, 4]]
dict2: [AnyHashable("key1"): [1, 2, 3, 4]]
are equal
========================
dict1: [AnyHashable("key1"): [1, 2, 3, 4]]
dict2: [AnyHashable("key1"): [2, 1, 3, 4]]
are equal
========================
dict1: [AnyHashable("key1"): [1, 2, 3, 4]]
dict2: [AnyHashable("key1"): [2, 1, 3]]
are not equal
========================
dict1: [AnyHashable("key1"): [1, 2, 3, 4]]
dict2: [AnyHashable("key1"): [1, 2, 3, "4"]]
are not equal
========================
dict1: [AnyHashable("key1"): ["key2": 2]]
dict2: [AnyHashable("key1"): ["key2": 2]]
are equal
========================
dict1: [AnyHashable("key1"): ["key2": 2]]
dict2: [AnyHashable("key1"): ["key2": 3]]
are not equal
========================
dict1: [AnyHashable("key1"): ["key2": 2]]
dict2: [AnyHashable("key1"): ["key2": 3]]
are not equal
Any
does not conform to Equatable
protocol. It is a must-have for a type if the ==
operator will be used. Therefore, you need to compare your Any
objects using a function that takes a type parameter as mentioned in this answer:
func isEqual<T: Equatable>(type: T.Type, a: Any, b: Any) -> Bool? {
guard let a = a as? T, let b = b as? T else { return nil }
return a == b
}
However, to use this function, you should know the exact type of each value in typingAttributes
. You can achieve this using the Mirror
struct as follows:
let lilAny: Any = "What's my type? :("
print(Mirror(reflecting: lilAny).subjectType) // String
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With