iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 10
0
Software Development

給我 30 天,給你一輩子:Swift 從零開始系列 第 10

Day 10 | Swift Collection Types 三部曲之終章:Dictionary

  • 分享至 

  • xImage
  •  

集合型別 ( Collection Types ):Dictionary

終於來到 Collection Types 三部曲最終章:Dictionary ,什麼是 Dictionary 呢?

我們先來看一段 API Response:

{
  "data": [{
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "JSON:API paints my bikeshed!",
      "body": "The shortest article. Ever.",
      "created": "2015-05-22T14:56:29.000Z",
      "updated": "2015-05-22T14:56:28.000Z"
    },
    "relationships": {
      "author": {
        "data": {"id": "42", "type": "people"}
      }
    }
  }]
}

可以發現在大括號中,有一對一對的資料,就好比 "type": "articles""id": "1" 或是 "data": {"id": "42", "type": "people"},這種沒有一定順序的 Key: Value 組合資料,就是 Dictionary,常被用來處理 API 回傳的資料。


Initialization

Dictionary 的宣告方式其實跟其他兩個集合型別也是很相似,Dictionary 宣告型別時,完整的寫法是這樣:

  • Dictionary<KeyType, ValueType>

所以假定今天有一個字串的 key,對上整數的 Value,你就可以這樣寫:

Dictionary<String, Int>

但是你也可以使用縮寫就會變成這樣:

[String: Int]

那麼以下的宣告方式都是相同的效果~

var 字典1: Dictionary<String, Int> = [:]
var 字典2 = Dictionary<String, Int>()
var 字典3: [String: Int] = [:]
var 字典4 = [String: Int]()

注意到這邊在給定初始值為空字典時,使用的是 [:]

透過宣告可以了解,這個 Dictionary 是被包在 [] 內,並且由一對一對的 String: Int 所組合而成的。

var 大兵日記: [String: String] = [:]
大兵日記 = ["日期": "2019-12-31", "天氣": "陰天", "心情": "爛透了"]

來看看上面的範例,在大兵日記這個 Dictionary,他是一個 [String: String],鍵跟值都是 String 型別,所以可以看到裡面有日期天氣以及心情對應到相對的值,而這三組資料每個都以 , 做區隔。

理所當然的,也可以不用特別註記型別就可以透過型別推論出型別喔,但是只局限於字典裡每組資料型別都是相同的( [String, String] 或是 [Int: String] ... )。

let countryCode = ["TW": "Taiwan", "JP": "Japan", "US": "United States"]
print("The Type of Country Code is \(type(of: countryCode))")
// The Type of Country Code is Dictionary<String, String>

Access and Modify

那為什麼會叫做 Dictionary 呢?其實這名稱其來有自,在取用 Dictionary 時,我們可以直接依照鍵來尋找值,就像查字典一樣,我們繼續以上面的 countryCode 來解釋:

print(countryCode["TW"])
// Optional("Taiwan")

針對 countryCode 使用 [key] 的方式來查詢,但是你有沒有發現,找出來的值為什麼不是 Taiwan 而是 Optional("Taiwan")

https://media.giphy.com/media/3o72F8t9TDi2xVnxOE/giphy.gif

還記得在基礎介紹時提到,Swift 其實對於程式碼安全性是很講究的,因為你並不能保證輸入的 Key 都一定能找到相對應的 Value,像是下面的範例,在字典中並沒有 "GB",所以在取用的時候會找不到值,也因為 Swift 程式碼安全,會回傳 nil,所以如果真的要針對取出來的值做進一步處理,最好的方式就是確保這個 Key 取出來是真的有值。

print(countryCode["GB"])
// nil
if let countryName = countryCode["TW"] {
	print("\(countryName) NO.1")
}

至於 count 以及 isEmpty 這兩個屬性,也是可以在 Dictionary 使用喔。

print(countryCode.count) // 3
print(countryCode.isEmpty) // false

Dictionary Modification

那如果今天想修改 Dictionary 裡面的值該如何做呢?還記得上面的取用方式嗎?

  • Dictionary[Key] = Value

找到值,並且指派新的值給它,這樣就可以修改值囉!

var 小胖便當價格表 = [
    "A餐": 100,
    "B餐": 200,
    "C餐": 300
]

小胖便當價格表["C餐"] = 400
print(小胖便當價格表["C餐"]!) // 400

除了可以修改既有的資料外,也可以新增資料,一樣是透過上述的方法來新增:

小胖便當價格表["D餐"] = 500
print(小胖便當價格表["D餐"]!)
// ["C餐": 400, "A餐": 100, "B餐": 200, "D餐": 500]

// 新增了 D餐: 500
// 因為 Dictionary 是跟 Set 一樣是無序排列
// 每一次印出來的順序也都不一樣喔 :)

除了使用這種方法,Dictionary 也有一個實體方法也可以新增資料:

  • updateValue(_:forKey:)

以上面修改及新增 C、D 餐的寫法,換成 updateValue,寫法就會像是這樣:

小胖便當價格表.updateValue(400, forKey:"C餐")
小胖便當價格表.updateValue(500, forKey:"D餐")

但是這上面都是在說如何修改 Value,但是可以修改 Key 嗎?

原則上不太建議,因為 Dictionary 會檢查 Key 是否實作 Hashable Protocol ,確保同一個 Dictionary 中,不會有重複的 Key,任意更改的結果可能就會同個 Dictionary 有兩組相同的 Key ,就會造成錯誤。

但是你真的要改的話也不是不行~

原則上建議先找到舊的 Key-Value,移除掉後再新增新的 Key,但是要怎麼移除資料呢?

  • removeValue(forKey:):就像取用的方式,依照 Key 來找尋,刪除
var exampleDictionary = [1: "A", 2: "B", 3: "C"]
exampleDictionary.removeValue(forKey: 3)
print(exampleDictionary) // [1: "A", 2: "B"]

exampleDictionary[4] = "C"
print(exampleDictionary) // [1: "A", 2: "B", 4: "C"]

這時候 3 就被替換成 4 了,也不會因為重複造成錯誤。

Iterating Over a Dictionary

Dictionary 實作了 Collection Protocol,理所當然地可以使用 for...in loop 走訪每組資料,但這邊就有些許的差異,如果你是想走訪每組資料,那就像先前一樣:

var exampleDictionary = [1: "A", 2: "B", 3: "C"]
for data in exampleDictionary {
	print(data)
}

/*
(key: 3, value: "C")
(key: 1, value: "A")
(key: 2, value: "B")
*/

但是你可以發現印出來的型別是一個 Tuple,所以我們也可以使用 Tuple 來去接收 Key 以及 Value

for (dataKey, dataValue) in exampleDictionary {
	print("Data Key = \(dataKey)")
	print("Data Value = \(dataValue)")
}

/*
Data Key = 1
Data Value = A
Data Key = 2
Data Value = B
Data Key = 3
Data Value = C
*/

冷知識

假定你想紀錄字典裡所有的 Keys 或是 Values,你可以使用 Dictionary.keys 以及 Dictionary.values,他會回傳整個 keys 或是 values,你可以宣告一個 Array 中來存放。

let dataKeys = [Int](exampleDictionary.keys)
// [1, 2, 3]

let dataValues = [String](exampleDictionary.values)
// ["A", "B", "C"]

上一篇
Day 9 | Swift Collection Types 三部曲之二部曲:Set
下一篇
Day 11 | Swift Collection Types 番外篇: Hashable Protocol
系列文
給我 30 天,給你一輩子:Swift 從零開始30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言