- Swift 5從零到精通iOS開發訓練營
- 張益琿編著
- 2709字
- 2022-07-27 18:32:08
3.4 集合類型
在Swift語言中一共提供了3種集合類型:數組(Array)、集合(Set)和字典(Dictionary)。數組類型是一種有序集合,放入其中的數據都有一個編號,且編號從0開始依次遞增。通過編號,開發者可以找到Array數組中對應的值。集合是一組無序的數據,其中存入的數據沒有編號,開發者可以使用遍歷的方法獲取其中所有的數據。集合是一種鍵值映射結構,其中每存入一個值都要對應一個特定的鍵,且鍵不能重復,開發者通過鍵可以直接獲取到對應的值。Swift官方開發文檔中的一張示例圖片可以十分清晰地描述這3種集合類型的異同,如圖3-1所示。

圖3-1 三種集合類型的異同
本節將介紹這三種集合類型的特點及操作數據的方法。
3.4.1 數組(Array)類型
數組中能夠存放的元素并非只是數字,它可以存放任意類型的數據,但是所有數據的類型必須統一。在實際開發中,數組中元素的類型決定了數組的類型,例如,一個存放整型數據的數組被稱為整型數組,一個存放字符串型數據的數組被稱為字符串型數組。在創建數組實例的時候,必須明確指定其中所存放元素的類型。使用Xcode開發工具創建一個名為CollectType的Playground,在其中編寫如下示例代碼:
//Int型數組 var array1:[Int] var array2:Array<Int>
上面兩行代碼都聲明了一個Int類型的數組實例,數組的創建可以使用兩種方式,一種是使用數組的構造方法來創建,另一種是使用中括號來快捷創建,示例如下:
//創建空數組 array1 = [] array2 = Array() //創建整型數組 array1 = [1,2,3] //通過一組元素創建數組 array2 = Array(arrayLiteral: 1,2,3)
提示
和String類型類似,空數組的含義并非是變量為nil,而是數組中的元素為空,Swift中只有Optional類型的變量可以為nil。
在Swift語言中,數組采用結構體來實現,對于大量重復元素的數組,開發者可以直接使用快捷方法來創建,示例如下:
//創建大量相同元素的數組 //創建有10個String類型元素的數組,并且每個元素都為字符串"Hello" var array3 = [String](repeating: "Hello", count: 10) //創建有10個Int類型元素的數組,且每個元素都為1 var array4 = Array(repeating: 1, count: 10)
讀者需要注意,數組在聲明時必須要明確其類型,但是開發者并不一定需要顯式地指定類型,如果數組在聲明時也設置了初始值,則編譯器會根據賦值類型自動推斷出數組的類型。數組數組中對加法運算符也進行了重載,開發者可以使用“+”進行兩個數組的相加,相加的結果即將第2個數組中的元素拼接到第1個數組后面。需要注意,相加的數組類型必須相同,示例如下:
//數組相加 array5 = [1,2,3,4,5,6] var array5 = [1,2,3]+[4,5,6]
數組中提供了許多方法供開發者來獲取數組實例的相關信息或者對數組進行增、刪、改、查的操作。示例如下:

這里需要注意,只有當數組實例為變量時,才可以使用增、刪、改等方法,常量數組不能進行與修改相關的操作。
開發者也可以使用for-in遍歷來獲取數組中的元素,示例如下:

可以直接對數組實例進行遍歷,Swift中的for-in結構和Objective-C中的for-in結構還是有一些區別的,Swift中的for-in結構在遍歷數組時會按照順序進行遍歷。數組實例中還有一個enumerated()方法,這個方法會返回一個元組集合,將數組的下標和對應元素返回。開發者也可以通過遍歷數組的下標來獲取數組中的元素,和String類型不同的是,數組中的下標可以是Int類型,而String中的下標是嚴格的Index類型,這里需要注意,不要混淆。
提示
數組類型中有一個indices屬性,這個屬性將返回一個范圍(Range),此范圍就是數組下標的范圍。
數組類型中還提供了一個排序函數,如果數組中的元素為整型數據,則可以使用系統提供的sorted(by:)方法來進行排序操作,如果是一些自定義的類型,開發者也可以對sorted(by:)方法傳入閉包參數實現新的排序規則,這部分內容會在后面章節中詳細介紹。進行數組排序的方法示例代碼如下:
var arraySort = [1,3,5,6,7] //從大到小排序 arraySort = arraySort.sorted(by: >) //從小到大排序 arraySort = arraySort.sorted(by: <)
下列方法可以獲取數組中的最大值與最小值:
var arraySort = [1,3,5,6,7] //獲取數組中的最大值 arraySort.max() //獲取數組中的最小值 arraySort.min()
3.4.2 集合(Set)類型
集合類型不關注元素的順序,但是其中的元素不可以重復,讀者也可以將其理解為一個無序的集合。與數組一樣,集合在聲明時必須指定其類型,或者對其賦初值,使得編譯器可以自行推斷出集合的類型。聲明與創建集合的示例代碼如下:
//創建set var set1:Set<Int> = [1,2,3,4] var set2 = Set(arrayLiteral: 1,2,3,4)
由于集合并不關注其中元素的順序,因此通過下標的方式來取值對集合來說不太有意義,但是集合類型依然支持通過下標來獲取其中的元素,示例如下:
//獲取集合首個元素(順序不定) set1[set1.startIndex] //進行下標的移動 //獲取某個下標后一個元素 set1[set1.index(after: set1.startIndex)] //獲取某個下標后幾個元素 set1[set1.index(set1.startIndex, offsetBy: 3)]
需要注意,集合的下標操作為不可逆的操作,只能向后移動,不能向前移動。
下面這個方法可以獲取集合實例中的一些信息:

集合同樣支持進行增、刪、改、查操作,示例如下:
//向集合中插入一個元素 set1.insert(5) //移除集合中的某個元素 set1.remove(1) //移除集合中的第一個元素 set1.removeFirst() //移除集合中某個位置的元素 set1.remove(at: set1.firstIndex(of: 3)!) //移除集合中所有的元素 set1.removeAll()
在使用remove(at:)方法刪除集合某個位置的元素時,需要傳入一個集合元素的下標值,通過集合實例的firstIndex(of:)方法可以獲取具體某個元素的下標值。需要注意,這個方法將會返回一個Optional類型的可選值,因為要尋找的元素可能不存在,在使用時,開發者需要對其進行拆包操作。
集合與數組除了有序和無序的區別外,集合還有一個獨有的特點:可以進行數學運算,例如交集運算、并集運算、補集運算等。Swift官方開發文檔中的一張圖片示意了集合進行數學運算時的場景,如圖3-2所示。

圖3-2 集合進行數學運算示意圖
從圖3-2中可以看出,集合支持4類數學運算,分別為intersection(交集)運算、symmetricDifference(交集的補集)運算、union(并集)運算和subtracting(補集)運算。交集運算的結果為兩個集合的交集,交集的補集運算的結果為a集合與b集合的并集除去a集合與b集合的交集,并集運算的結果為兩個集合的并集,補集運算的結果為a集合除去a集合與b集合的交集。上述4種運算的示例代碼如下:
var set3:Set<Int> = [1,2,3,4] var set4:Set<Int> = [1,2,5,6] //返回交集 {1,2} var setInter = set3.intersection(set4) //返回交集的補集{3,4,5,6} var setEx = set3.symmetricDifference(set4) //返回并集{1,2,3,4,5,6} var setUni = set3.union(set4) //返回第二個集合的補集{3,4} var setSub = set3.subtracting(set4)
使用比較運算符“==”可以比較兩個集合是否相等,當兩個集合中的所有元素都相等時,兩個集合才相等。集合中還提供了一些方法用于判斷集合間的關系,示例代碼如下:
var set5:Set = [1,2] var set6:Set = [2,3] var set7:Set = [1,2,3] var set8:Set = [1,2,3] //判斷是否是某個集合的子集,set5是set7的子集,返回ture set5.isSubset(of: set7) //判斷是否是某個集合的超集,set7是set5的超集,返回ture set7.isSuperset(of: set5) //判斷是否是某個集合的真子集,set5是set7的真子集,返回ture set5.isStrictSubset(of: set7) //判斷是否是某個集合的真超集,set7不是set8的真超集,返回false set7.isStrictSuperset(of: set8)
與數組類似,集合也可以通過for-in遍歷的方式來獲取所有集合中的數據,可以通過3種方法來進行遍歷:遍歷元素、遍歷集合的枚舉與遍歷集合的下標。集合枚舉會返回一個元組,元組中將集合下標和其對應的值一同返回,示例代碼如下:

集合雖然不強調元素順序,但是在遍歷時,開發者可以對其進行排序后再遍歷,示例如下:
//從大到小排序再遍歷集合 for item in set7.sorted(by: >) { print(item) }
3.4.3 字典(Dictionary)類型
字典是生活中常用的學習工具,字典在使用時是由一個索引找到一個結果。例如,英漢詞典通過英文單詞可以找到其對應的漢語解釋,成語詞典通過成語可以找到其對應的意義解釋,等等。這種數據的存儲模式被稱為鍵值映射模式,即通過一個確定的鍵可以找到一個確定的值。類比上面的例子,在英漢詞典中,英文單詞就是鍵,漢語釋義就是值;在成語詞典中,成語就是鍵,意義解釋就是值。在Swift語言中也有這樣的一種Dictionary集合,即字典集合類型。
Swift中的任何類型在聲明時都必須明確其類型,通過對Array和Set的學習,讀者應該知道,對于集合類型,在聲明時務必明確其內部元素的類型,字典也不例外,由于字典中的一個元素實際上是由鍵和值兩部分組成的,因此在聲明字典時,也需要明確其鍵和值的類型。有兩種方式可以進行字典的聲明或創建,示例代碼如下:
//聲明字典[param1:param2],這種結構用于表示字典類型,param1為鍵類型,param2為值類型 var dic1:[Int:String] //這種方式和[:]效果一樣,dic2與dic1為相同的類型 var dic2:Dictionary<Int,String> //字典創建與賦值 dic1 = [1:"1",2:"2",3:"3"] dic2 = Dictionary(dictionaryLiteral: (1,"1"),(2,"2"),(3,"3")) //在創建字典時,也可以不顯式聲明字典的類型,可以通過賦初值的方式來使編譯器自動推斷 var dic3 = ["1":"one"] //創建空字典 var dic4:[Int:Int] = [:] var dic5:Dictionary<Int,Int> = Dictionary()
需要注意,字典通過鍵來找到特定的值,在字典中值可以重復,但是鍵必須唯一。這樣才能保證一個確定的鍵能找到一個確定的值,并且如果開發者在字典中創建重復的鍵,編譯器也會報出錯誤。
字典類型也支持使用isEmpty與count來判斷是否為空并獲取元素個數,示例代碼如下:
//獲取字典中的元素個數 dic1.count //判斷字典是否為空 if dic4.isEmpty{ print("字典為空") }
通過具體鍵可以獲取與修改對應的值,示例如下:
//通過鍵操作值 //獲取值 dic1[2] //修改值 dic1[1]="0" //添加一對新的鍵值 dic1[4] = "4"
上面代碼中的dic1[1]="0"與dic1[4]="4"實際上完成了相同的操作,可以這樣理解:在對某個鍵進行賦值時,如果這個鍵存在,則會進行值的更新,如果這個鍵不存在,則會添加一對新的鍵值。然而在開發中,很多情況下需要對一個存在的鍵進行更新操作,如果這個鍵不存在,則不添加新鍵值對,要實現這種效果,可以使用字典的更新鍵值方法,示例代碼如下:
//對鍵值進行更新 dic1.updateValue("1", forKey: 1)
updateValue(value:forkey:)方法用于更新一個已經存在的鍵值對,其中第1個參數為新值,第2個參數為要更新的鍵。這個方法在執行時會返回一個Optional類型的值,如果字典中此鍵存在,則會更新成功,并將鍵的舊值包裝成Optional值返回,如果此鍵不存在,則會返回nil。在開發中,常常使用if-let結構來處理,示例如下:
//使用if let 處理updateValue的返回值 if let oldValue = dic1.updateValue("One", forKey: 1) { print("Old Value is \(oldValue)") }
其實在通過鍵來獲取字典中的值時,也會返回一個Optional類型的值,如果鍵不存在,則此Optional值為nil,因此也可以使用if-let結構來保證程序的安全性,示例如下:
//通過鍵獲取的數據也將返回Optional類型的值,也可以使用if let if let value = dic2[1] { print("The Value is \(value)") }
下面的方法可以實現對字典中鍵值對的刪除操作:
//通過鍵刪除某個鍵值對 dic1.removeValue(forKey: 1) //刪除所有鍵值對 dic1.removeAll()
在對字典進行遍歷操作時,可以遍歷字典中所有鍵組成的集合,也可以遍歷字典中所有值組成的集合,通過字典實例的keys屬性與values屬性分別可以獲取字典的所有鍵與所有值,示例代碼如下:

如以上代碼所示,也可以直接對字典實例進行遍歷,遍歷中會返回一個元組類型包裝字典的鍵和值。
在進行字典鍵或者值的遍歷時,也支持對其進行排序遍歷,實例如下:
