比较 Swift 中的两个 [String: Any] 字典 4
Comparing two [String: Any] dictionaries in Swift 4
我有两个词典用作 [String: Any]
类型的文本属性,为了打开或关闭所需的属性,我需要检查两个词典是否相同。
我尝试了以下方法:
let current = inputTextView.typingAttributes
let undo = current.elementsEqual(attributes, by: { (arg0, arg1) -> Bool in
return ((arg0.key == arg1.key) && (arg0.value == arg1.value))
})
但是在第二次评估时我得到了错误:
Binary operator '==' cannot be applied to two 'Any' operands
比较两个类型 [String: Any]
的字典的最佳方法是什么??
谢谢
Any
不符合 Equatable
协议。如果要使用 ==
运算符,它是类型的必备条件。因此,您需要使用带有类型参数的函数来比较 Any
对象,如 :
中所述
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
}
但是,要使用此函数,您应该知道 typingAttributes
中每个值的确切类型。您可以使用 Mirror
结构实现此目的,如下所示:
let lilAny: Any = "What's my type? :("
print(Mirror(reflecting: lilAny).subjectType) // String
详情
- Xcode 版本 10.3 (10G8), Swift 5
解决方案
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
我有两个词典用作 [String: Any]
类型的文本属性,为了打开或关闭所需的属性,我需要检查两个词典是否相同。
我尝试了以下方法:
let current = inputTextView.typingAttributes
let undo = current.elementsEqual(attributes, by: { (arg0, arg1) -> Bool in
return ((arg0.key == arg1.key) && (arg0.value == arg1.value))
})
但是在第二次评估时我得到了错误:
Binary operator '==' cannot be applied to two 'Any' operands
比较两个类型 [String: Any]
的字典的最佳方法是什么??
谢谢
Any
不符合 Equatable
协议。如果要使用 ==
运算符,它是类型的必备条件。因此,您需要使用带有类型参数的函数来比较 Any
对象,如
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
}
但是,要使用此函数,您应该知道 typingAttributes
中每个值的确切类型。您可以使用 Mirror
结构实现此目的,如下所示:
let lilAny: Any = "What's my type? :("
print(Mirror(reflecting: lilAny).subjectType) // String
详情
- Xcode 版本 10.3 (10G8), Swift 5
解决方案
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