Swift 字典 (Dictionaries)

字典是一種用來儲存多個相同型別數值的容器。每個數值 (Value) 都關聯著一個唯一的鍵 (Key)。與陣列不同,字典裡的元素是沒有順序的。

你可以把它想像成現實生活中的字典:你透過查詢一個「單字」(Key) 來找到它的「解釋」(Value)。

建立字典

鍵和值的型別必須明確。例如 [String: Int] 代表這是一個「鍵為字串,值為整數」的字典。

var airports: [String: String] = ["TPE": "Taipei Taoyuan", "NRT": "Tokyo Narita"]

// Swift 自動推斷型別
var codeNames = ["TPE": "Taipei Taoyuan"]

建立空字典:

var namesOfIntegers: [Int: String] = [:]
// 或
var emptyDict = [Int: String]()

存取與修改字典

取得元素數量 .count

print("共有 \(airports.count) 個機場")

檢查是否為空 .isEmpty

if airports.isEmpty {
    print("字典是空的")
}

新增或更新值 .updateValue

使用下標語法 (Subscript Syntax):

// 新增一個新的鍵值對
airports["LHR"] = "London"

// 更新現有的鍵值對
airports["LHR"] = "London Heathrow"

你也可以使用 updateValue(_:forKey:) 方法,它的好處是會回傳更新前的舊值 (如果有的話),這對於檢查更新是否成功很有用。

if let oldValue = airports.updateValue("Dublin Airport", forKey: "DUB") {
    print("原本的值是 \(oldValue),現在更新了")
}

移除值 .removeValue

將某個鍵的值設為 nil 即可移除該鍵值對:

airports["APL"] = "Apple International"
airports["APL"] = nil // "APL" 被移除了

或者使用 removeValue(forKey:)

if let removedValue = airports.removeValue(forKey: "DUB") {
    print("移除了 \(removedValue)")
}

遍歷字典

使用 for-in 迴圈遍歷字典,每次迭代會得到一個 (key, value) 的元組:

for (airportCode, airportName) in airports {
    print("\(airportCode): \(airportName)")
}

如果你只想遍歷所有的鍵或所有的值 .keys .values

for code in airports.keys {
    print("Airport code: \(code)")
}

for name in airports.values {
    print("Airport name: \(name)")
}

常用高階函式 (Higher Order Functions)

字典也支援許多高階函式,但使用上與陣列稍有不同,因為字典包含鍵與值。

MapValues 轉換值 (.mapValues)

很多時候我們只想修改字典的「值」而保留原本的「鍵」,這時候 mapValues 非常好用。

let prices = ["Apple": 100, "Banana": 50, "Orange": 80]
let discountedPrices = prices.mapValues { $0 * 0.9 } // 打九折
// ["Apple": 90.0, "Banana": 45.0, "Orange": 72.0] (順序不固定)
注意:如果你直接使用 map,會得到一個 Array (陣列),而不是 Dictionary。

Filter 過濾 (.filter)

使用 filter 來篩選鍵值對。回傳的結果預設是一個 [(Key, Value)] 的陣列 (Array of Tuples),但在 Swift 4 以後,你可以直接建立新的字典。

let scores = ["Alice": 90, "Bob": 55, "Charlie": 80]
let passed = scores.filter { $0.value >= 60 }
// pass 是一個字典 ["Alice": 90, "Charlie": 80]

Grouping 分組

Dictionary(grouping:by:) 是一個非常強大的功能,可以將一個陣列根據某個條件分組,轉換成字典。

let names = ["Alice", "Bob", "Charlie", "David"]
let groupedByFirstLetter = Dictionary(grouping: names) { $0.first! }
// Key 是首字母,Value 是該首字母的名字陣列
// ["A": ["Alice"], "B": ["Bob"], "C": ["Charlie"], "D": ["David"]]