如何在Swift中实现C++ unordered_set的异构类型O(1)包含查询
Swift实现跨类型O(1)哈希集合查询的方案
Swift原生Set出于类型安全设计,contains方法仅支持传入与集合元素同类型的参数,没有C++的透明哈希重载机制,但可以通过以下两种方案实现同等能力:
方案1:直接使用字典替代Set(最简洁)
你的需求核心是仅通过公共的data字段做唯一判定,直接用data作为键、First实例作为值的Swift原生字典即可实现,完全满足O(1)时间复杂度要求:
首先定义基础结构体:
struct First { let data: Int let otherData: String } struct Second { let data: Int let otherData: Int }
使用示例:
// 存储容器,等效于自定义哈希规则的Set var storage: [Int: First] = [:] // 插入元素 storage[100] = First(data: 100, otherData: "test") // 用First类型查询 let queryFirst = First(data: 100, otherData: "bla") print(storage[queryFirst.data] != nil) // 输出 true // 用Second类型查询 let querySecond = Second(data: 100, otherData: 1000) print(storage[querySecond.data] != nil) // 输出 true
方案2:封装通用自定义集合(适用复杂场景)
如果需要保留Set的完整API能力,或者后续需要扩展更多可查询类型,可以基于公共协议封装通用容器:
步骤1:定义公共标识协议
// 所有可参与查询的类型都实现该协议,返回用于唯一判定的标识 protocol IdentityHashable { associatedtype Key: Hashable var identityKey: Key { get } } // 给First、Second扩展实现协议 extension First: IdentityHashable { var identityKey: Int { data } } extension Second: IdentityHashable { var identityKey: Int { data } }
步骤2:封装自定义集合
struct CustomHashSet<T: IdentityHashable> { private var storage: [T.Key: T] = [:] /// 插入元素 mutating func insert(_ element: T) { storage[element.identityKey] = element } /// 跨类型查询,只要查询对象实现了IdentityHashable协议即可 func contains<Q: IdentityHashable>(_ query: Q) -> Bool where Q.Key == T.Key { storage[query.identityKey] != nil } // 可按需扩展remove、count、遍历等Set原生能力 }
使用示例
var set = CustomHashSet<First>() set.insert(First(data: 100, otherData: "test")) print(set.contains(First(data: 100, otherData: "bla"))) // true print(set.contains(Second(data: 100, otherData: 1000))) // true
两种方案的时间复杂度都和原生Set/字典一致,插入、查询均为O(1),符合性能要求。
内容的提问来源于stack exchange,提问作者whatisgoingon
相关产品推荐
相关产品推荐

