標籤:swift ios
字典
字典是一種儲存相同類型多重資料的儲存空間。每個值(value)都關聯獨特的鍵(key),鍵作為字典中的這個值資料的標識符。和數組中的資料項目不同,字典中的資料項目並沒有具體順序。我們在需要通過標識符(鍵)訪問資料的時候使用字典,這種方法很大程度上和我們在現實世界中使用字典查字義的方法一樣。
Swift 的字典使用時需要具體規定可以儲存鍵和值類型。不同於 Objective-C 的NSDictionary和NSMutableDictionary 類可以使用任何類型的對象來作鍵和值並且不提供任何關於這些對象的本質資訊。在 Swift 中,在某個特定字典中可以儲存的鍵和值必須提前定義清楚,方法是通過顯性類型標註或者類型推斷。
Swift 的字典使用Dictionary<KeyType,ValueType>定義,其中KeyType是字典中鍵的資料類型,ValueType是字典中對應於這些鍵所儲存值的資料類型。
KeyType的唯一限制就是可雜湊的,這樣可以保證它是獨一無二的,所有的 Swift 基本類型(例如String,Int, Double和Bool)都是預設可雜湊的,並且所有這些類型都可以在字典中當做鍵使用。未關聯值的枚舉成員(參見枚舉)也是預設可雜湊的。
字典字面語句
我們可以使用字典字面語句來構造字典,他們和我們剛才介紹過的數組字面語句擁有相似文法。一個字典字面語句是一個定義擁有一個或者多個鍵值對的字典集合的簡單語句。
一個鍵值對是一個key和一個value的結合體。在字典字面語句中,每一個鍵值對的鍵和值都由冒號分割。這些鍵值對構成一個列表,其中這些鍵值對由方括弧包含並且由逗號分割:
[key 1: value 1, key 2: value 2, key 3:value 3]
下面的例子建立了一個儲存國際機場名稱的字典。在這個字典中鍵是三個字母的國際航空運輸相關代碼,值是機場名稱:
var airports: Dictionary<String,String> = ["TYO": "Tokyo", "DUB":"Dublin"]
airports字典被定義為一種Dictionary<String,String>,它意味著這個字典的鍵和值都是String類型。
注意:
airports字典被聲明為變數(用var關鍵字)而不是常量(let關鍵字)因為後來更多的機場資訊會被添加到這個樣本字典中。
airports字典使用字典字面語句初始化,包含兩個鍵值對。第一對的鍵是TYO,值是Tokyo。第二對的鍵是DUB,值是Dublin。
這個字典語句包含了兩個String: String類型的鍵值對。他們對應airports變數聲明的類型(一個只有String鍵和String值的字典)所以這個字典字面語句是構造兩個初始資料項目的airport字典。
和數組一樣,如果我們使用字面語句構造字典就不用把類型定義清楚。airports的也可以用這種方法簡短定義:
var airports = ["TYO":"Tokyo", "DUB": "Dublin"]
因為這個語句中所有的鍵和值都分別是相同的資料類型,Swift 可以推斷出Dictionary<String, String>是airports字典的正確類型。
讀取和修改字典
我們可以通過字典的方法和屬性來讀取和修改字典,或者使用下標文法。和數組一樣,我們可以通過字典的唯讀屬性count來擷取某個字典的資料項目數量:
println("The dictionary of airportscontains \(airports.count) items.")// 列印 "Thedictionary of airports contains 2 items."(這個字典有兩個資料項目)
我們也可以在字典中使用下標文法來添加新的資料項目。可以使用一個合適類型的 key 作為下標索引,並且分配新的合適類型的值:
airports["LHR"] ="London"// airports 字典現在有三個資料項目
我們也可以使用下標文法來改變特定鍵對應的值:
airports["LHR"] = "LondonHeathrow"// "LHR"對應的值 被改為 "LondonHeathrow
作為另一種下標方法,字典的updateValue(forKey:)方法可以設定或者更新特定鍵對應的值。就像上面所示的樣本,updateValue(forKey:)方法在這個鍵不存在對應值的時候設定值或者在存在時更新已存在的值。和上面的下標方法不一樣,這個方法返回更新值之前的原值。這樣方便我們檢查更新是否成功。
updateValue(forKey:)函數會返回包含一個字典值類型的可選值。舉例來說:對於儲存String值的字典,這個函數會返回一個String?或者“可選 String”類型的值。如果值存在,則這個可選值值等於被替換的值,否則將會是nil。
if let oldValue =airports.updateValue("Dublin Internation", forKey: "DUB") { println("The old value for DUB was \(oldValue).")}// 輸出 "The oldvalue for DUB was Dublin."(dub原值是dublin)
我們也可以使用下標文法來在字典中檢索特定鍵對應的值。由於使用一個沒有值的鍵這種情況是有可能發生的,可選類型返回這個鍵存在的相關值,否則就返回nil:
if let airportName =airports["DUB"] { println("The name of the airport is \(airportName).")} else { println("That airport is not in the airports dictionary.")}// 列印 "The name ofthe airport is Dublin INTernation."(機場的名字是都柏林國際)
我們還可以使用下標文法來通過給某個鍵的對應值賦值為nil來從字典裡移除一個鍵值對:
airports["APL"] = "AppleInternation"// "Apple Internation"不是真的 APL機場, 刪除它airports["APL"] = nil// APL現在被移除了
另外,removeValueForKey方法也可以用來在字典中移除鍵值對。這個方法在鍵值對存在的情況下會移除該鍵值對並且返回被移除的value或者在沒有值的情況下返回nil:
if let removedValue =airports.removeValueForKey("DUB") { println("The removed airport's name is \(removedValue).")} else { println("The airports dictionary does not contain a value forDUB.")}// prints "The removed airport's nameis Dublin International."
字典遍曆
我們可以使用for-in迴圈來遍曆某個字典中的鍵值對。每一個字典中的資料項目都由(key, value)元組形式返回,並且我們可以使用暫時性常量或者變數來分解這些元組:
for (airportCode, airportName) in airports{ prINTln("\(airportCode): \(airportName)")}// TYO: Tokyo// LHR: London Heathrow
for-in迴圈請參見For 迴圈。
我們也可以通過訪問他的keys或者values屬性(都是可遍曆集合)檢索一個字典的鍵或者值:
for airportCode in airports.keys { prINTln("Airport code: \(airportCode)")}// Airport code: TYO// Airport code: LHR for airportName in airports.values { prINTln("Airport name: \(airportName)")}// Airport name: Tokyo// Airport name: London Heathrow
如果我們只是需要使用某個字典的鍵集合或者值集合來作為某個接受Array執行個體 API 的參數,可以直接使用keys或者values屬性直接構造一個新數組:
let airportCodes = Array(airports.keys)// airportCodes is ["TYO","LHR"] let airportNames = Array(airports.values)// airportNames is ["Tokyo","London Heathrow"]
注意:
Swift 的字典類型是無序集合類型。其中字典鍵,值,鍵值對在遍曆的時候會重新排列,而且其中順序是不固定的。
建立一個空字典
我們可以像數組一樣使用構造文法建立一個空字典:
var namesOfIntegers = Dictionary<Int,String>()// namesOfIntegers 是一個空的Dictionary<Int, String>
這個例子建立了一個Int, String類型的空字典來儲存英語對整數的命名。他的鍵是Int型,值是String型。
如果上下文已經提供了資訊類型,我們可以使用空字典字面語句來建立一個空字典,記作[:](中括弧中放一個冒號):
namesOfIntegers[16] = "sixteen"// namesOfIntegers 現在包含一個索引值對namesOfIntegers = [:]// namesOfIntegers 又成為了一個 Int,String類型的空字典
注意:
在後台,Swift 的數組和字典都是由泛型集合來實現的,想瞭解更多泛型和集合資訊請參見泛型。
集合的可變性
數組和字典都是在單個集合中儲存可變值。如果我們建立一個數組或者字典並且把它分配成一個變數,這個集合將會是可變的。這意味著我們可以在建立之後添加更多或移除已存在的資料項目來改變這個集合的大小。與此相反,如果我們把數組或字典分配成常量,那麼他就是不可變的,它的大小不能被改變。
對字典來說,不可變性也意味著我們不能替換其中任何現有鍵所對應的值。不可變字典的內容在被首次設定之後不能更改。不可變行對數組來說有一點不同,當然我們不能試著改變任何不可變數組的大小,但是我們·可以重新設定相對現存索引所對應的值。這使得 Swift 數組在大小被固定的時候依然可以做的很棒。
Swift 數組的可變性行為同時影響了數組執行個體如何被分配和修改,想擷取更多資訊,請參見集合在賦值和複製中的行為。
注意:
在我們不需要改變數組大小的時候建立不可變數組是很好的習慣。如此 Swift 編譯器可以最佳化我們建立的集合