You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何按插入顺序一致获取字典的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.15 15:24:03