首页 / Swift 编程语言教程 / 字典 Dictionary

Swift 编程语言教程

字典 Dictionary

本教程共 93 篇 · 第 19 篇 · 更新于 2026-08-08 · 约 8 分钟阅读

SwiftSwift 编程语言教程字典Dictionary键值对哈希下标

本节目标:读完你能用字典存键值对、按键取值、安全地增删改,并理解为什么按下标取值会返回可选值。

字典用来存”键—值”配对:每个值都挂在一个唯一键上,靠键来查找。就像现实里的字典,用”词”查”释义”。这一章讲字典的模型和日常操作。

1-1 字典的模型

字典是无序的”键—值”集合。同一个键只对应一个值;键必须可哈希(和 Set 一样),值没有此限制。适合”按标识查内容”的场景,比如用机场三字码查机场名、用用户名查资料。

完整类型写法 Dictionary<键, 值>,简写 [键: 值] 是主流:

var airports: [String: String] = ["YYZ": "多伦多", "DUB": "都柏林"]

[String: String] 读作”键是字符串、值也是字符串的字典”。

1-2 声明与推断

如果字典字面量里键和值各自类型一致,类型也能推断:

var airports = ["YYZ": "多伦多", "DUB": "都柏林"]   // [String: String]

建空字典有两种等价写法:

var namesOfIntegers: [Int: String] = [:]
var empty = [Int: String]()

当上下文能推断类型时,[:] 这个空字典字面量最简洁。namesOfIntegers = [:] 能清空但保留类型。

1-3 添加与修改

用下标语法加新键值对——把新键当下标,赋上新值:

airports["LHR"] = "伦敦"

改已有键的值也一样,下标赋值会覆盖:

airports["LHR"] = "伦敦希思罗"

另一种改法是 updateValue(_:forKey:),它设值或更新,并返回”旧值”(可选类型):

if let old = airports.updateValue("都柏林机场", forKey: "DUB") {
    print("DUB 的旧值是 \(old)")
}

返回旧值的好处是你能知道”这次到底改了没有”。如果键原本没有,返回 nil 表示是新增。

1-4 按键取值返回可选值

这是字典最容易让新手迷糊的点:用下标按键取值,返回的是”可选值”。因为你要的键可能根本不存在。

if let name = airports["DUB"] {
    print("机场名是 \(name)")
} else {
    print("字典里没有这个机场")
}

如果键存在,下标返回”包着值的可选”;不存在则返回 nil。所以取出来的值类型是 String? 而非 String,得解包才能用——这正是 Swift 强制你处理”查不到”的情况。

1-5 删除键值对

把某个键的值设为 nil,就删掉了这对:

airports["APL"] = "某机场"
airports["APL"] = nil   // APL 被删除

更正式地用 removeValue(forKey:),它返回被删的值(可选),没有则返回 nil

if let removed = airports.removeValue(forKey: "DUB") {
    print("删掉的机场名是 \(removed)")
}

1-6 查数量与判空

和数组、Set 一致,count 看对数,isEmpty 判空:

print("字典有 \(airports.count) 对")
if airports.isEmpty {
    print("空字典")
}

1-7 遍历字典

for-in 遍历时,每一对以 (键, 值) 元组形式给出,解构即可:

for (code, name) in airports {
    print("\(code): \(name)")
}

只想要键或只想要值,用 keys / values 属性:

for code in airports.keys {
    print("代码:\(code)")
}
for name in airports.values {
    print("名称:\(name)")
}

1-8 把键或值转成数组

如果某个 API 要的是数组,可以用 keys/values 直接初始化一个新数组:

let codes = [String](airports.keys)
let names = [String](airports.values)

注意字典本身无序,所以 codesnames 的顺序不保证和插入顺序一致。需要确定顺序时,对 keysvaluessorted()

1-9 与数组、Set 的对比

三种集合怎么选?数组:要顺序、可重复、按下标取。Set:要自动去重、高频查”有没有”、做集合运算。字典:要”按键查值”、每值有唯一标识。

它们都类型安全,都可用 let/var 控制可变性,都要求元素/键可哈希。理解了这组分工,数据结构选型就不慌了。

Warning

字典的键必须可哈希,所以不能用 ArraySet 当键(它们本身可变、不可哈希)。好消息是基础类型都能当键。另外,按键取值永远返回可选值,别忘记解包。

1-10 字典的取货逻辑

字典是”按键查值”的容器,模型像现实字典:用”词”查”释义”。日常按标识取内容的场景(机场码查机场名、用户名查资料)都离不开它。声明用 [键: 值] 简写,键必须可哈希,值无此限制。

加/改用下标赋值或 updateValue(_:forKey:)(返回旧值,能知道这次是改还是增);删用设 nilremoveValue(forKey:)count/isEmpty 看状态,for-in 遍历得 (键, 值) 元组,keys/values 取单边,还能直接初始化成数组。

最该牢记的坑:按键取值返回”可选值”。因为键可能不存在,下标返回 String? 而非 String,必须解包才能用。这是 Swift 强制你处理”查不到”的情况,是安全设计而非麻烦。理解这点,你就不会对着”为什么取出来不能直接拼”发懵。

与数组、Set 对比:数组要顺序可重复、按下标取;Set 要自动去重、高频查”有没有”、做集合运算;字典要”按键查值”、每值有唯一标识。三者都类型安全、都可用 let/var 控可变性、都要求元素/键可哈希。理解这组分工,数据结构选型就不慌。

一个易错点:字典的键必须可哈希,所以不能用数组或集合当键(它们可变、不可哈希);基础类型都能当键。另外按键取值永远返回可选值,别忘记解包——这是新手查字典时最常被编译器”教育”的地方。把”查得到吗”当成每次按键的固定思考,代码就稳了。字典在真实项目里无处不在:配置表、缓存、计数表(用字典统计词频)、JSON 解析后的容器,几乎都是它。把”键唯一、取值返回可选”这两条刻进习惯,你就能放心地用字典组织任何”标识—内容”数据,而不必担心偷偷拿到 nil 导致崩溃。

1-11 补记:字典做计数器

再补一个常见用法:用字典做”计数器”特别自然。比如统计一段文字里每个字符出现几次,键是字符、值是次数,遇到就 counts[char, default: 0] += 1。这里 字典[键, default: 0] 的写法很贴心:键不存在时返回默认 0,省去手动判空。这个 idiom 在做词频、投票、分组统计时极常用。

字典还有个细节:遍历时元素的顺序不保证和插入顺序一致(除非用有序字典类型)。所以别依赖遍历顺序做事,需要顺序就显式 sorted()。把”键唯一、取值返回可选、顺序不定”三点记牢,字典就能成为你组织”标识—内容”数据最可靠的容器。

补充一点:字典嵌套(如 [String: [Int]])很常见,表示”一个键对应一组值”。取值时记得外层下标返回可选(键可能不存在),内层数组访问也要合法,层层解包别慌,一步步来就好。

1-12 小结

字典 [键: 值] 是无序键值对,键必须可哈希。加/改用下标赋值或 updateValue(_:forKey:)(返回旧值),删用设 nilremoveValue(forKey:)。按键取值返回可选值,因为键可能不存在——这是 Swift 逼你处理”查不到”的安全设计。count/isEmpty 看状态,for-in 遍历得 (键, 值) 元组,keys/values 取单边。下一章我们看集合的高阶操作:用 map/filter/reduce 等函数式手法处理数据。