我可以比较2个词典是否匹配:
func ==(lhs: [String: AnyObject], rhs: [String: AnyObject] ) -> Bool {
return NSDictionary(dictionary: lhs).isEqualToDictionary(rhs)
}
是否有一种简洁的方法来提取两个字典之间的差异,就像交叉点的相反一样?
答案 0 :(得分:6)
我们可以定义一个运算符来检查2个字典是否包含相同的键,并且每个键包含相同的值。
首先,我们需要使用泛型来要求Value
字典符合Equatable
,否则我们无法比较这些值。
这是代码
func ==<Value:Equatable>(left: [String: Value], right: [String: Value]) -> Bool {
guard left.keys.count == right.keys.count else { return false }
let differenceFound = zip(left.keys.sort(), right.keys.sort()).contains { elm -> Bool in
let leftKey = elm.0
let rightKey = elm.1
return leftKey != rightKey || left[leftKey] != right[rightKey]
}
return !differenceFound
}
第一行验证字典具有相同数量的条目,否则返回false
。
下一个代码块对两个字典的键进行排序,并比较每对字符串,以查找键或值不同的一对。
如果没有找到这样的差异,那么词典具有相同的键和值,因此它们是相等的。
["a":1, "b": 2] == ["a":1, "b": 2] // true
当然,由于词典中的值没有订单,以下内容仍然存在
["a":1, "b": 2] == ["b":2, "a": 1] // true
在下一个例子中,我们将2个词典与不同数量的值进行比较
["a":1, "b": 2] == ["a":1, "b": 2, "c": 3] // false
由于我们定义了==
运算符,Swift为我们提供了!=
运算符(它只返回==
的反面),所以我们也可以写
["a":1, "b": 2] != ["d":4] // true
同样的操作符也可以用这种较短的方式编写
func ==<Value:Equatable>(left: [String: Value], right: [String: Value]) -> Bool {
return
left.keys.count == right.keys.count &&
!zip(left.keys.sort(), right.keys.sort()).contains { $0 != $1 || left[$0] != right[$1] }
}
现在提供了2个词典a
和b
,您希望执行a.minus(b)
并获取包含{{1}中可用的所有(key, value)
对的新词典。 {和a
中没有。
这是代码
b
实施例
extension Dictionary where Key: Comparable, Value: Equatable {
func minus(dict: [Key:Value]) -> [Key:Value] {
let entriesInSelfAndNotInDict = filter { dict[$0.0] != self[$0.0] }
return entriesInSelfAndNotInDict.reduce([Key:Value]()) { (res, entry) -> [Key:Value] in
var res = res
res[entry.0] = entry.1
return res
}
}
}
答案 1 :(得分:2)
Swift supports operations like symmetricDifference(:) and subtracting(:),但是对于集合而言,不是字典。根据您的需要,您可以对键进行区分,然后使用地图重建结果字典。