Swift中存储S1的Set如何以O(1)复杂度判断是否包含S2实例
解决方案
Swift 原生的 Set 是强类型泛型集合,Set<S1> 的默认 contains 方法只能接受 S1 类型参数,直接传入 S2 实例会编译报错。可以通过以下方案实现需求,全程保持 O(1) 时间复杂度:
方案1:扩展 Set 重载 contains 方法(最简便)
因为 S1 的相等判断、哈希计算都只依赖 data 字段,我们可以构造仅填充 data 字段的临时 S1 实例传入原生 contains 方法即可,临时实例的 otherData 可以随意填充,不会影响判断结果:
extension Set where Element == S1 { /// 支持传入 S2 实例查询是否存在 func contains(_ s2: S2) -> Bool { // 构造临时占位 S1,otherData 随意填写,不影响判等和哈希结果 let dummyS1 = S1(data: s2.data, otherData: "") return contains(dummyS1) } }
调用方式完全符合预期:
let obj: S2 = ... set.contains(obj) // 直接调用,O(1) 复杂度
方案2:抽取公共协议减少重复代码(适合多相似类型场景)
如果后续还有更多类似 S1、S2 的类型,哈希和判等都依赖 data 字段,可以抽取公共协议统一实现,避免每个类型都写重复的判等、哈希逻辑:
// 定义公共协议,要求实现 data 字段 protocol DataHashable: Hashable { var data: String { get } } // 给协议添加默认的判等、哈希实现,统一仅依赖 data extension DataHashable { static func == (lhs: Self, rhs: Self) -> Bool { lhs.data == rhs.data } func hash(into hasher: inout Hasher) { hasher.combine(data) } } // S1、S2 遵守协议即可,无需单独写判等和哈希逻辑 struct S1: DataHashable { let data: String let otherData: String } struct S2: DataHashable { let data: String let otherData: Int }
后续新增同规则类型只要遵守 DataHashable 协议即可,再配合方案1的 Set 扩展就能实现跨类型查询。
注意事项
- 请确保 S1 的判等、哈希逻辑永远仅依赖
data字段,若后续修改了 S1 的相关逻辑记得同步更新 Set 扩展的实现,避免出现判断错误。 - 临时构造的 S1 占位实例开销极低,不会影响性能。
内容的提问来源于stack exchange,提问作者user16783018
相关产品推荐
相关产品推荐

