字典是 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)]