集合類型
本節內容包括:
Swift 語言里的數組和字典中存儲的數據值類型必須明確。
注意: Swift 的數組結構在被聲明成常量和變量或者被傳入函數與方法中時會相對于其他類型展現出不同的特性。
<a name = "數組"></a>數組
Swift 數組特定于它所存儲元素的類型。這與 Objective-C 的 NSArray 和 NSMutableArray 不同,這兩個類可以存儲任意類型的對象,并且不提供所返回對象的任何特別信息。在 Swift 中,數據值在被存儲進入某個數組之前類型必須明確,方法是通過顯式的類型標注或類型推斷,而且不是必須是class類型。例如: 如果我們創建了一個Int值類型的數組,我們不能往其中插入任何不是Int類型的數據。 Swift 中的數組是類型安全的,并且它們中包含的類型必須明確。
數組的簡單語法
寫 Swift 數組應該遵循像Array<SomeType>這樣的形式,其中SomeType是這個數組中唯一允許存在的數據類型。 我們也可以使用像[SomeType]這樣的簡單語法。
數組構造語句
可以使用字面量來進行數組構造,這是一種用一個或者多個數值構造數組的簡單方法。
var shoppingList: [String] = ["Eggs", "Milk"]
// shoppingList 已經被構造并且擁有兩個初始項。
//注意: Shoppinglist數組被聲明為變量(var關鍵字創建)而不是
//常量(let創建)是因為以后可能會有更多的數據項被插入其中。
訪問和修改數組
我們可以通過數組的方法和屬性來訪問和修改數組,或者下標語法。 還可以使用數組的只讀屬性count來獲取數組中的數據項數量。
println("The shopping list contains \(shoppingList.count) items.")
// 輸出"The shopping list contains 2 items."(這個數組有2個項)
使用布爾項isEmpty
來作為檢查count
屬性的值是否為 0 的捷徑。
if shoppingList.isEmpty {
println("The shopping list is empty.")
} else {
println("The shopping list is not empty.")
}
// 打印 "The shopping list is not empty."(shoppinglist不是空的)
也可以使用append
方法在數組后面添加新的數據項:
shoppingList.append("Flour")
// shoppingList 現在有3個數據項,有人在攤煎餅
使用加法賦值運算符(+=)也可以直接在數組后面添加一個或多個擁有相同類型的數據項:
shoppingList += ["Baking Powder"]
// shoppingList 現在有四項了
shoppingList += ["Chocolate Spread","Cheese","Butter"]
// shoppingList 現在有七項了
數組的遍歷
我們可以使用for-in
循環來遍歷所有數組中的數據項:
for item in shoppingList {
println(item)
}
for (index, value) in enumerate(shoppingList) {
println("Item \(String(index + 1)): \(value)")
}
<a name = "集合"></a>集合
集合用來存儲相同類型并且沒有確定順序的值。當集合元素順序不重要時或者希望確保每個元素只出現一次時可以把集合當做是數組另一形式。
Set類型語法
Swift中的Set類型被寫為Set<SomeType>,這里的SomeType表示Set中允許存儲的類型,和數組不同的是,集合沒有等價的簡化形式。
創建和構造一個Set
可以通過構造器語法創建一個特定類型的空集合:
var letters = Set<Character>()
集合與數組字面量
你可以使用一個數組字面量來構造一個集合,并且可以使用簡化形式寫一個或者多個值作為集合元素。
var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]
一個Set類型不能從數組中字面量中獨立地被推斷出來,因此Set類型必須顯式聲明。然而,由于Swift的類型推導功能,如果你想使用一個數組字面量構造一個Set并且該數組字面量中的所有元素類型相同,那么你無須寫出Set的具體類型。
訪問和修改一個Set
為了找出一個Set
中元素的數量,可以使用其只讀屬性count
:
println("I have \(favoriteGenres.count) favorite music genres.")
使用布爾屬性isEmpty
作為一個縮寫形式去檢查count
屬性是否為0:
if favoriteGenres.isEmpty {
println("As far as music goes, I'm not picky.")
} else {
println("I have particular music preferences.")
}
你可以通過調用Set
的insert(_:)
方法添加一個新的元素:
favoriteGenres.insert("Jazz")
你可以通過調用Set
的remove(_:)
方法去刪除一個元素,如果該值是該Set
的一個元素則刪除該元素并且返回被刪除的元素值,否認如果該Set
不包含該值,則返回nil
。另外,Set
中的所有元素可以通過它的removeAll()
方法刪除。
使用contains(_:)
方法去檢查Set
中是否包含一個特定的值。
遍歷一個Set
你可以在一個for-in
循環中遍歷一個Set
中的所有值。
for genre in favoriteGenres {
println("\(value)")
}
Swift的Set類型沒有確定的順序,為了按照特定順序來遍歷一個Set中值可以使用全局sorted函數,它將根據提供的序列返回一個排序的集合.
for genre in sorted(favoriteGenres) {
println("\(genre)")
}
完成集合操作
- 使用
union(_:)
方法根據兩個集合的值創建一個新的集合。 - 使用
subtract(_:)
方法根據不在該集合中的值創建一個新的集合。 - 使用
intersect(_:)
方法根據兩個集合中都包含的值創建的一個新的集合。 - 使用
exclusiveOr(_:)
方法根據值在一個集合中但不在兩個集合中的值創建一個新的集合。
Set類型的哈希值
為了存儲在集合中,該類型必須是可哈希化的-也就是說,該類型必須提供一個方法來計算它的哈希值。一個哈希值是Int類型的,它和其他的對象相同,其被用來比較相等與否,比如a==b,它遵循的是a.hashValue == b.hashValue。
注意 你可以使用你自定義的類型作為集合的值或者是字典的鍵值類型,但你需要使你的自定義類型服從Swift標準庫中的Hashable協議。服從Hashable協議的類型需要提供一個類型為Int的取值訪問器屬性hashValue。這個由類型的hashValue返回的值不需要在同一程序的不同執行周期或者不同程序之間保持相同。 因為hashable協議服從于Equatable協議,所以遵循該協議的類型也必須提供一個"是否等"運算符(==)的實現。這個Equatable協議需要任何遵循的==的實現都是一種相等的關系。也就是說,對于a,b,c三個值來說,==的實現必須滿足下面三種情況:
- a==a(自反性)
- a==b意味著b==a(對稱性)
- a==b&&b==c意味著a==c(傳遞性)
<a name = "字典"></a>字典
字典是一種存儲多個相同類型的值的容器。每個值(value)都關聯唯一的鍵(key),鍵作為字典中的這個值數據的標識符。
Swift 的字典使用時需要具體規定可以存儲鍵和值類型。不同于 Objective-C 的NSDictionary和NSMutableDictionary 類可以使用任何類型的對象來作鍵和值并且不提供任何關于這些對象的本質信息。在 Swift 中,在某個特定字典中可以存儲的鍵和值必須提前定義清楚,方法是通過顯性類型標注或者類型推斷。
Swift 的字典使用Dictionary<KeyType, ValueType>定義,其中KeyType是字典中鍵的數據類型,ValueType是字典中對應于這些鍵所存儲值的數據類型。
字典字面量
var airports: [String:String] = ["TYO": "Tokyo", "DUB": "Dublin"]
讀取和修改字典
我們可以通過字典的方法和屬性來讀取和修改字典,或者使用下標語法。和數組一樣,我們可以通過字典的只讀屬性count
來獲取某個字典的數據項數量:
println("The dictionary of airports contains \(airports.count) items.")
可以在字典中使用下標語法來添加新的數據項
airports["LHR"] = "London"
也可以使用下標語法來改變特定鍵對應的值:
airports["LHR"] = "London Heathrow"
字典的updateValue(forKey:)方法可以設置或者更新特定鍵對應的值。
字典遍歷
我們可以使用for-in循環來遍歷某個字典中的鍵值對。每一個字典中的數據項都由(key, value)元組形式返回,并且我們可以使用臨時常量或者變量來分解這些元組:
for (airportCode, airportName) in airports {
println("\(airportCode): \(airportName)")
}
<a name = "集合的可變性"></a>集合的可變性
數組和字典都是在單個集合中存儲可變值。如果我們創建一個數組或者字典并且把它分配成一個變量,這個集合將會是可變的。這意味著我們可以在創建之后添加更多或移除已存在的數據項來改變這個集合的大小。與此相反,如果我們把數組或字典分配成常量,那么它就是不可變的,它的大小不能被改變。