Swift中提供了三種基本的集合類型來存儲集合數據:
- 數組(Arrays) 有序的數據的集
- 集合(Sets) 無序無重復的數據集
- 字典(Dictionaries) 無序的鍵值對值
Swift中
Arrays
、Sets
和Dictionaries
,這意味著我們不能把不正確的數據類型插入其中.同時這也說明我們完全可以對取回值的類型非常自信.
集合的可變性
Swift中Arrays
、Sets
和Dictionaries
被var 和let 修飾的生活,和其他類型的數據的原理是一樣的,var 修飾的時候,是變量,可修改他們里面的值,let 修飾的時候,是常量,常量不可變.
Arrays
//數組使用有序列表存儲同一類型的多個值俩檬。相同的值可以多次出現在一個數組的不同位置中.
//這個與OC中的數組的概念有點不一樣,OC中的數組可以存放不同類型的對象,但是不能存放基礎類型
//如何定義一個包含Int 類型的數組
var intItems = [Int]() //中括號,包含一個類型,然后接一個小括號
intItems.append()
someInts.append(1)
someInts.append(2)
//someInts.append("a")//這個寫法編譯出錯
print(someInts) // [1 ,2]
//因為上面再定義數組intItems是指定了它只能存放Int類型,
//所以在調用Arrays的.append()方法時系統(tǒng)也會提示只能放入Int類型的值
創(chuàng)建一個帶有默認值的Array
//創(chuàng)建一個簡單的 Int 類型 常量數組
let array = [1,2]
print(array) // [1,2]
//創(chuàng)建一個簡單的Double 類型 變量數組
var threeDoubles = Array(repeating: 0.0, count: 3)
print(threeDoubles) //[0.0, 0.0, 0.0]
//通過兩個數組相加得到另外一個數組
var anotherThreeDoubles = Array(repeating: 2.5, count: 3)//[2.5, 2.5, 2.5]
var sixDoubles = threeDoubles + anotherThreeDoubles
//sixDoubles 等于 [0.0, 0.0, 0.0, 2.5, 2.5, 2.5]
訪問和修改數組
var shoppintList = ["蘋果","土豆","雞肉","牛肉"]
//通過.count屬性獲得數組的元素個數
print("shoppingList contain \(shoppintList.count) items")
//輸出 :shoppingList contain 4 items
//判斷數組是否為空
if shoppingList.isEmpty {
print("YES")
}else{
print ( "NO" )
}//輸出結果 NO
//使用.append()方法追加元素
shoppintList.append("鴨肉")
//此時shoppintList等于["蘋果", "土豆", "雞肉", "牛肉", "鴨肉"]
//使用 += 運算符在變量數組后追加另外一個數組
shoppingList += ["青菜","烏龜"]
//此時shoppintList等于["蘋果", "土豆", "雞肉", "牛肉", "鴨肉","青菜","烏龜"]
//使用數組的下標來訪問數值中的元素,與OC的使用方法一樣
let firstItem = shoppingList[0] //這里firstItem會被判定為String類型
print(firstItem) //輸出 "蘋果"
//使用下標來改變數組中對應的值
shoppingList[0] = "雞蛋"
//此時shoppingList 等于 ["雞蛋", "土豆", "雞肉", "牛肉", "鴨肉","青菜","烏龜"]
//insert(_:at:)方法插入一個元素
shoppintList.insert("蘋果", at: 0)
//此時shoppintList等于 ["蘋果","雞蛋", "土豆", "雞肉", "牛肉", "鴨肉","青菜","烏龜"]
//remove(at: )方法刪除一個元素
shoppingList.remove(at: 7)
print(shoppingList)//["蘋果", "雞蛋", "土豆", "雞肉", "牛肉", "鴨肉", "青菜"]
//還可以利用下標來一次改變一系列數據值脆丁,即使新數據和原有數據的數量是不一樣的英染。
shoppingList[4...6] = ["abc","bcd"]
//["蘋果", "雞蛋", "土豆", "雞肉", "abc", "bcd"]
數組的遍歷
for item in shoppingList {
print(item)
}
//蘋果
//雞蛋
//土豆
//雞肉
//abc
//bcd
for (index, value) in shoppingList. enumerated() {
print("Item \(String(index + 1)): \(value)")
}
// Item 1: 蘋果
// Item 2: 雞蛋
// Item 3: 土豆
// Item 4: 雞肉
// Item 5: abc
// Item 6: bcd
集合(Sets)
集合(Set)用來存儲相同類型并且沒有確定順序的值。當集合元素順序不重要時或者希望確保每個元素只出現一次時可以使用集合而不是數組。(重點:Sets的元素是不重復的)
Sets類型的哈希值(hash)
一種類型的數據為了能夠存在Sets中,它的類型必須是可以被哈細化的.哈希值是一種Int類型,兩個相等的數據,它的哈希值是一樣的,例如a = b , 那么a.hashValue == b.hashValue. Swift的基本類型都是可以哈希化的,沒有關聯值的枚舉成員值(在枚舉有講述)默認也是可哈献菔疲化的。
注意:
你可以使用你自定義的類型作為集合的值的類型或者是字典的鍵的類型管钳,但你需要使你的自定義類型符合 Swift 標準庫中的Hashable協議.符合Hashable協議的類型需要提供一個類型為Int的可讀屬性hashValue钦铁。由類型的hashValue屬性返回的值不需要在同一程序的不同執(zhí)行周期或者不同程序之間保持相同。
因為Hashable協議符合Equatable協議才漆,所以遵循該協議的類型也必須提供一個"是否相等"運算符(==)的實現牛曹。這個Equatable協議要求任何符合==實現的實例間都是一種相等的關系。也就是說醇滥,對于a,b,c三個值來說黎比,==的實現必須滿足下面三種情況:
a == a(自反性)
a == b意味著b == a(對稱性)
a == b && b == c意味著a == c(傳遞性)
關于遵循協議的更多信息,請看協議
集合類型語法
Swift 中的Set類型被寫為Set<Element>腺办,這里的Element表示Set中允許存儲的類型焰手,和數組不同的是糟描,集合沒有等價的簡化形式.(因為直接等價的被推斷成了Arrays
)
創(chuàng)建和構造一個空的集合
var letters = Set<Character>()
//通過構造器怀喉,這里的letters變量的類型被推斷為Set<Character>。
print("letters的類型是:Set<Character>,包含\(letters.count) 個元素.")
// 打印 "letters的類型是Set<Character>,包含0個元素."
letters.insert("a")
// letters 現在含有1個 Character 類型的值
letters = []
// letters 現在是一個空的 Set, 但是它依然是 Set<Character> 類型
//利用數組來創(chuàng)建Set
var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]
// favoriteGenres 被構造成含有三個初始值的集合
//上面的寫法還可以簡化為下面的代碼
//var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"]
訪問和修改一個集合
//你可以通過Set的屬性和方法來訪問和修改一個Set船响。
//Set類型和Arrays一樣,擁有.count方法來獲取它的元素個數
print("favoriteGenres的元素個數是:\(favoriteGenres.count)個")
//輸出:favoriteGenres的元素個數是:3個
//使用布爾屬性isEmpty作為一個縮寫形式去檢查count屬性是否為0:
if favoriteGenres.isEmpty {
print("As far as music goes, I'm not picky.")
} else {
print("I have particular music preferences.")
}
// 打印 "I have particular music preferences."
//你可以通過調用Set的insert(_:)方法來添加一個新元素:
favoriteGenres.insert("Jazz")
// favoriteGenres 現在包含4個元素
//你可以通過調用Set的remove(_:)方法去刪除一個元素,
//如果該值是該Set的一個元素則刪除該元素并且返回被刪除的元素值躬拢,
//否則如果該Set不包含該值,則返回nil见间。
//另外聊闯,Set中的所有元素可以通過它的removeAll()方法刪除。
if let removedGenre = favoriteGenres.remove("Rock") {
print("\(removedGenre)? I'm over it.")
} else {
print("I never much cared for that.")
}
// 打印 "Rock? I'm over it."
//使用contains(_:)方法去檢查Set中是否包含一個特定的值
if favoriteGenres.contains("Funk") {
print("I get up on the good foot.")
} else {
print("It's too funky in here.")
}
// 打印 "It's too funky in here."
//遍歷一個集合
for genre in favoriteGenres {
print("\(genre)")
}
// Classical
// Jazz
// Hip hop
//為了按照特定順序來遍歷一個Set中的值可以使用sorted()方法,它將返回一個有序數組
for genre in favoriteGenres.sorted() {
print("\(genre)")
}
// prints "Classical"
// prints "Hip hop"
// prints "Jazz
集合操作
你可以高效地完成Set的一些基本操作米诉,比如把兩個集合組合到一起菱蔬,判斷兩個集合共有元素,或者判斷兩個集合是否全包含,部分包含或者不相交拴泌。
- 使用intersection(_:)方法根據兩個集合中都包含的值創(chuàng)建的一個新的集合魏身。
- 使用symmetricDifference(_:)方法根據在一個集合中但不在兩個* 集合中的值創(chuàng)建一個新的集合。
- 使用union(_:)方法根據兩個集合的值創(chuàng)建一個新的集合蚪腐。
- 使用subtracting(_:)方法根據不在該集合中的值創(chuàng)建一個新的集合箭昵。
let oddDigits: Set = [1, 3, 5, 7, 9]
let evenDigits: Set = [0, 2, 4, 6, 8]
let singleDigitPrimeNumbers: Set = [2, 3, 5, 7]
oddDigits.union(evenDigits).sorted()
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
oddDigits. intersection(evenDigits).sorted()
// []
oddDigits.subtracting(singleDigitPrimeNumbers).sorted()
// [1, 9]
oddDigits. symmetricDifference(singleDigitPrimeNumbers).sorted()
// [1, 2, 9]
集合成員關系和相等
- 使用“是否相等”運算符(==)來判斷兩個集合是否包含全部相同的值。
- 使用isSubset(of:)方法來判斷一個集合中的值是否也被包含在另外一個集合中回季。
- 使用isSuperset(of:)方法來判斷一個集合中包含另一個集合中所有的值家制。
- 使用isStrictSubset(of:)或者isStrictSuperset(of:)方法來判斷一個集合是否是另外一個集合的子集合或者父集合并且兩個集合并不相等。
- 使用isDisjoint(with:)方法來判斷兩個集合是否不含有相同的值(是否沒有交集)泡一。
let houseAnimals: Set = ["??", "??"]
let farmAnimals: Set = ["??", "??", "??", "??", "??"]
let cityAnimals: Set = ["??", "??"]
houseAnimals.isSubset(of: farmAnimals)
// true
farmAnimals.isSuperset(of: houseAnimals)
// true
houseAnimals.isSuperset(of: armAnimals)
//true
farmAnimals.isStrictSuperset(of: houseAnimals)
// true
farmAnimals.isDisjoint(with: cityAnimals)
// true
字典
Swift 的字典使用Dictionary<Key, Value>定義颤殴,其中Key是字典中鍵的數據類型,Value是字典中對應于這些鍵所存儲值的數據類型瘾杭。
一個字典的Key類型必須遵循Hashable協議诅病,就像Set的值類型。在同一個字典中,一個key不可以出現兩次,但是value可以重復出現
也可以用[Key: Value]這樣簡化的形式去創(chuàng)建一個字典類型粥烁。雖然這兩種形式功能上相同贤笆,但是后者是首選
//創(chuàng)建一個空字典
var namesOfIntegers = [Int: String]()
// namesOfIntegers 是一個空的 [Int: String] 字典,它的鍵是Int型,值是String型讨阻。
//我們可以使用空字典字面量來創(chuàng)建一個空字典芥永,記作[:]
namesOfIntegers[16] = "sixteen"
// namesOfIntegers 現在包含一個鍵值對
namesOfIntegers = [:]
// namesOfIntegers 又成為了一個 [Int: String] 類型的空字典
//用字典字面量創(chuàng)建字典
//下面的例子創(chuàng)建了一個存儲國際機場名稱的字典。在這個字典中鍵是三個字母的國際航空運輸相關代碼钝吮,值是機場名稱:
var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
//airports字典被聲明為一種[String: String]類型埋涧,這意味著這個字典的鍵和值都是String類型。
//airports字典使用字典字面量初始化奇瘦,包含兩個鍵值對棘催。
//第一對的鍵是YYZ,值是Toronto Pearson耳标。第二對的鍵是DUB醇坝,值是Dublin。
訪問和修改字典
var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
print(" airports contains \(airports.count) items.")
//airports contains 2 items.
//使用布爾屬性isEmpty作為一個縮寫形式去檢查count屬性是否為0:
let emptyOrNot = airports.isEmpty
//emptyOrNot 為否
//使用下標語法來添加新的數據項
airports["LHR"] = "London"
// airports 字典現在有三個數據項
//使用下標語法來改變特定鍵對應的值:
airports["LHR"] = "London Heathrow"
// "LHR"對應的值 被改為 "London Heathrow
//還可以用字典的方法updateValue(_:forKey:)方法可以設置或者更新特定鍵對應的值次坡。
//updateValue(_:forKey:) 的功能和上面的一樣
//不同的是:updateValue(_:forKey:)這個方法返回更新值之前的原value呼猪。
//這樣使得我們可以檢查更新是否成功。
guard let str = airports.updateValue("香港", forKey: "GZ") else {
print("str is empty")
return
}
//此時:airports 等于:["YYZ": "Toronto Pearson", "DUB": "Dublin", "LHR": "London", "GZ": "廣州"]
//也可以使用下標語法來在字典中檢索特定鍵對應的值,
//因為key對應的value可能為nil ,
//所以下標訪問方法返回的是對應值的可選類型
if let airportName = airports["GZ"] {
print(airportName)
} else {
print("沒有對應的機場")
}
// 打印:廣州
//把指定key 對應的 value 設置為 nil, 則這對鍵值對會被從字典移除
airports["GZ"] = nil
print(airports)
//["YYZ": "Toronto Pearson", "DUB": "Dublin", "LHR": "London"]
//此外砸琅,removeValue(forKey:)方法也可以用來在字典中移除鍵值對宋距。
//這個方法在鍵值對存在的情況下會移除該鍵值對并且返回被移除的值或者在沒有值的情況下返回nil
if let removedValue = airports. removeValue(forKey: "DUB") {
print("removedValue")
} else {
print("沒有對應的機場")
}
//輸出: Dublin
字典遍歷
//for-in循環(huán)來遍歷某個字典中的鍵值對
var person = ["老王":38,"老李":28,"小李":18]
for (name, age) in person {
print("\(name): \(age)")
}
//老李: 28
//小李: 18
//老王: 38
//通過訪問keys訪問遍歷values
for age in person.keys {
print(age)
}
//小李
//老李
//牛愛花
//老王
//通過values 訪問keys
for key in person.values{
print(key)
}
//18
//28
//28
//38
//如果我們只是需要使用某個字典的鍵集合或者值集合
//可以直接使用keys或者values屬性構造一個新數組:
let names = [String](person.keys)
print(names) //["小李", "老李", "牛愛花", "老王"]
let ages = [Int](person.values)
print(ages)//[18, 28, 28, 38]