如何按插入顺序一致获取字典的key和value?有无替代存储方案?
问题原因
Swift 标准库中的Dictionary是基于哈希表实现的无序集合,本身不承诺保留元素的插入顺序,也没有任何配置项可以开启顺序保留。同时为了防范哈希碰撞攻击,每次App运行时都会随机生成哈希种子,这就导致你每次运行时取出keys、values的顺序都不固定,仅能保证key和value的对应关系正确,和插入顺序没有关联。
解决方案
原生字典无法满足保留插入顺序的需求,可通过以下两种方案实现:
方案1:零依赖自定义有序字典
自己封装有序字典结构,用数组记录key的插入顺序,搭配原生字典存储键值对,兼顾O(1)查找效率和顺序保留:
struct OrderedDictionary<Key: Hashable, Value> { // 存储按插入顺序排列的key private var keysArray: [Key] = [] // 存储键值对保证查询效率 private var dictionary: [Key: Value] = [:] /// 存入键值对 mutating func setValue(_ value: Value, forKey key: Key) { if dictionary[key] == nil { keysArray.append(key) } dictionary[key] = value } /// 根据key取值 func value(forKey key: Key) -> Value? { dictionary[key] } /// 按插入顺序返回所有key var orderedKeys: [Key] { keysArray } /// 按插入顺序返回所有value var orderedValues: [Value] { keysArray.compactMap { dictionary[$0] } } /// 下标访问 subscript(key: Key) -> Value? { get { dictionary[key] } set { guard let newValue = newValue else { // 处理删除逻辑 dictionary.removeValue(forKey: key) keysArray.removeAll { $0 == key } return } setValue(newValue, forKey: key) } } }
使用示例:
var sampleDic = OrderedDictionary<String, Any>() sampleDic["one"] = 1 sampleDic["two"] = 2 sampleDic["three"] = 3 print("keys: \(sampleDic.orderedKeys)") print("Values: \(sampleDic.orderedValues)") // 输出固定为: // keys: ["one", "two", "three"] // Values: [1, 2, 3]
方案2:使用官方现成有序字典
苹果官方开源的Swift Collections组件中提供了生产级别的OrderedDictionary实现,API和原生字典完全兼容,仅需替换变量声明即可直接使用,自动保留插入顺序。
临时场景无需复用时,可以单独维护一个存储插入顺序的Key数组,每次给字典赋值的同时把新Key追加到数组末尾,需要输出时遍历该数组取对应value即可,无需额外封装。
内容的提问来源于stack exchange,提问作者MK iOS
相关产品推荐
相关产品推荐

