Swift字典比较优化:无需转数组即可排除指定键的实现方案
解决Swift字典比较扩展直接接受Dictionary.Keys参数的问题
我帮你调整这个Dictionary扩展,让它可以直接接收car.keys这类Dictionary.Keys类型的参数,不用再手动转成Array。先拆解下问题核心:
你当前的扩展里,excluding参数的类型是固定数组[Key],但car.keys返回的是Dictionary.Keys——这是Swift字典自带的自定义序列类型,并非Array,所以直接传入会触发类型不匹配的编译错误。要解决这个问题,只需要把参数类型放宽到任意遵循Sequence协议的Key序列即可。
修改后的扩展代码
extension Dictionary where Key: Equatable { func isEqualTo<ExcludedKeys: Sequence>(_ dictionary: Dictionary, excluding: ExcludedKeys = []) -> Bool where ExcludedKeys.Element == Key { // 转成Set优化contains查询效率,尤其是排除键数量较多时 let excludedSet = Set(excluding) let left = filter { !excludedSet.contains($0.key) } let right = dictionary.filter { !excludedSet.contains($0.key) } return NSDictionary(dictionary: left).isEqual(to: right) } }
改动说明
- 泛型Sequence约束:通过泛型
ExcludedKeys并约束它遵循Sequence且元素为Key,这样所有Key的序列类型(包括Dictionary.Keys、Set<Key>、普通Array)都能直接传入,无需额外类型转换。 - 性能优化:将传入的序列转成
Set<Key>,因为Set的contains操作是O(1)时间复杂度,而数组的contains是O(n),当需要排除的键较多时,这个优化能明显提升比较速度。
现在可以直接调用啦
// 不用再写Array(car.keys),直接传car.keys即可 foo.isEqualTo(bar, excluding: car.keys)
如果你的Swift版本在5.7及以上,还可以用更简洁的any Sequence<Key>写法,效果完全一致:
extension Dictionary where Key: Equatable { func isEqualTo(_ dictionary: Dictionary, excluding: any Sequence<Key> = []) -> Bool { let excludedSet = Set(excluding) let left = filter { !excludedSet.contains($0.key) } let right = dictionary.filter { !excludedSet.contains($0.key) } return NSDictionary(dictionary: left).isEqual(to: right) } }
内容的提问来源于stack exchange,提问作者nambatee
相关产品推荐
相关产品推荐

