字典是 Swift 的主要集合类型之一。 字典存储唯一的键与对应的值之间的无序关联。 字典中的所有键必须是同一类型,所有值也必须具有相同的类型。
字典字面量由逗号分隔的key: value对组成,并用方括号括起来:
var addresses: Dictionary<String, String> = [
"The Munsters": "1313 Mockingbird Lane",
"The Simpsons": "742 Evergreen Terrace",
"Buffy Summers": "1630 Revello Drive"
]
var sequences: [String: [Int]] = [
"Euler's totient": [1, 1, 2, 2, 4, 2, 6, 4],
"Lazy caterer": [1, 2, 4, 7, 11, 16, 22, 29, 37],
"Carmichael": [561, 1105, 1729, 2465, 2821, 6601, 8911, 10585, 15841]
]
let constants = [
"pi": 3.14159,
"e": 2.71828,
"phi": 1.618033,
"avogadro": 6.02214076e23
]
字典类型有两种显式的写法:Dictionary<Key, Value>,或者简写语法[Key: Value]。
要创建空字典,需要显式指定它的键类型和值类型:
var emptyDict1: [Int: Int] = [:]
var emptyDict2 = [Character: String]()
var emptyDict3 = Dictionary<Int, Double>()
你可以使用下标语法访问值:把键放在字典名后面的方括号里。
由于某个键可能不在字典中,下标访问会返回一个可选值(Value?)。
如果键存在,Swift 会返回被包装的值;如果不存在,就返回nil:
let munster: String? = addresses["The Munsters"]
// Returns Optional("1313 Mockingbird Lane")
let carmichael = sequences["Carmichael"]
// Returns Optional([561, 1105, 1729, 2465, 2821, 6601, 8911, 10585, 15841])
let planck = constants["planck"]
// Returns nil
为了避免处理可选值,你可以使用default形参提供一个默认值:
let e: Double = constants["e", default: 0]
// Returns 2.71828
let hoagie: [Int] = sequences["Hoagie", default: []]
// Returns []
let betty = addresses["Betty Cooper", default: "Address unknown"]
// Returns "Address unknown"
对于用var声明的可变字典,你可以使用下标赋值来添加或更新键值对:
sequences["Euler's totient"]?.append(contentsOf: [6, 4])
// sequences["Euler's totient"] is now [1, 1, 2, 2, 4, 2, 6, 4, 6, 4]
addresses["Betty Cooper"] = "111 Queens Ave."
addresses["Betty Cooper", default: "Address unknown"]
// Returns "111 Queens Ave."
constants["Gelfond's"] = 23.140692
// Compiler error: Cannot assign through subscript: 'constants' is a 'let' constant
你可以使用for-in循环迭代字典中的每个键值对。
每一项都以(key, value)元组的形式提供:
for (name, address) in addresses {
print("\(name) lives at \(address)")
}
由于字典是无序的,对它排序会得到一个由键值对组成的数组。
你可以给sorted(by:)方法传入一个闭包,让它比较两个(key, value)元组,如果第一个元组应该排在第二个之前,就返回true:
func sortByNameLengthThenValue(_ lhs: (key: String, value: Double), _ rhs: (key: String, value: Double)) -> Bool {
let left = lhs.value + Double(lhs.key.count)
let right = rhs.value + Double(rhs.key.count)
return left < right
}
let sortedConstants = constants.sorted(by: sortByNameLengthThenValue)
在本练习中,你要实现一种记录你当地街机厅里最热门游戏高分的方式。
你有 7 个函数要实现,它们都和返回以及操作一个高分数据字典有关。
创建一个函数 newScoreBoard(),它不接受任何形参,并返回一个新的高分字典,其中键的类型为String,值的类型为Int。
要把玩家添加到高分字典中,请定义 addPlayer(_:_:_:),这是一个接受 3 个形参的函数:
var highScores = newScoreBoard()
addPlayer(&highScores, "Dave Thomas")
// Returns ["Dave Thomas": 0]
addPlayer(&highScores, "José Valim", 486_373)
// Returns ["Dave Thomas": 0, "José Valim": 486_373]
要把玩家从高分字典中移除,请定义 removePlayer(_:_:),它接受 2 个形参:
如果该玩家在字典中,这个函数应把他从字典中移除,否则什么也不做。
var highScores = ["Dave Thomas": 0, "José Valim": 486_373]
removePlayer(&highScores, "Dave Thomas")
// Returns ["José Valim": 486_373]
removePlayer(&highScores, "Rose Fanaras")
// Returns ["José Valim": 486_373]
要重置玩家的分数,请定义 resetPlayer(_:_:),它接受 2 个形参:
这个函数会把玩家的分数设为 0。 如果玩家不在字典中,则什么也不应发生。
var highScores = ["Dave Thomas": 486_373, "José Valim": 10]
resetScore(&highScores, "Dave Thomas")
// Returns ["Dave Thomas": 0, "José Valim": 10]
要通过在之前的分数上累加来更新玩家的分数,请定义 updateScore,它接受 3 个形参:
var highScores = ["Dave Thomas": 0, "José Valim": 486_373]
addPlayer(&highScores, "Freyja Ćirić", 12_771_008)
updateScore(&highScores, "Freyja Ćirić", 73)
// Returns ["Dave Thomas": 0, "José Valim": 486_373, "Freyja Ćirić": 12_771_081]
定义函数 orderByPlayers,它接受 1 个形参:
这个函数会返回一个由 (String, Int) 元组组成的数组,其中是玩家及其高分,按玩家姓名升序排列。
var highScores = ["Dave Thomas": 0, "José Valim": 486_373, "Freyja Ćirić": 12_771_091]
orderByPlayers(highScores)
// Returns [("Dave Thomas", 0), ("Freyja Ćirić", 12_771_091), ("José Valim", 486_373)]
要获取按分数降序排列的玩家数组,请定义 orderByScores,它接受 1 个形参:
这个函数会返回一个由 (String, Int) 元组组成的数组,其中是玩家及其高分,按玩家分数降序排列。
var highScores = ["Dave Thomas": 0, "José Valim": 486_373, "Freyja Ćirić": 12_771_091]
orderByScores(highScores)
// Returns [("Freyja Ćirić", 12_771_091), ("José Valim", 486_373), ("Dave Thomas", 0)]