在本教程中,您將了解集合,創(chuàng)建集合,修改集合以及集合中的一些常見操作。
在上一篇Swift 數(shù)組文章中,我們了解了如何創(chuàng)建可以在一個有序列表中包含多個值的數(shù)組。
但是,如果我們要確保列表只能唯一值,那么我們使用Swift中的set(集合)。
集合只是一個容器,可以在無序列表中保存多個數(shù)據(jù)類型的值,并確保容器中的元素唯一(即每個數(shù)據(jù)僅出現(xiàn)一次)。
無序列表意味著您將無法按照定義集合中的項的順序獲得元素。
使用集合而不是數(shù)組的主要優(yōu)點是,當您需要確保一個項只出現(xiàn)一次,并且項的順序并不重要時。
存儲在集合中的值必須是散列的。這意味著它必須提供hashValue屬性。這一點很重要,因為集合是無序的,它使用hashValue來訪問集合的元素。
默認情況下,Swift的所有基本類型(如String、Int、Double和Bool)都是可散列的,并且可以用作設置值類型。但是,您也可以在Swift中創(chuàng)建可以存儲在集合中的散列類型。
通過將類型指定為set,然后指定它可以存儲在<>中的數(shù)據(jù)類型,也可以創(chuàng)建空集。
let emptyIntSet:Set= [] print(emptyIntSet)
或者
let emptyIntSet:Set= Set() print(emptyIntSet)
運行該程序時,輸出為:
[ ]
在上面的程序中,我們聲明了一個Set 類型常量 emptyInt ,該常量集合 可以存儲多個整數(shù)值并使用0值初始化。
由于Swift是一種類型推斷語言,因此您也可以不指定數(shù)據(jù)類型而直接創(chuàng)建 set 集合,但是必須使用一些值進行初始化,以便編譯器可以將其類型推斷為:
let someIntSet:Set = [1, 2, 3, 4, 5, 6, 7, 8, 9] print(someIntSet)
運行該程序時,輸出為:
[2, 4, 9, 5, 6, 7, 3, 1, 8]
在上面的程序中,我們聲明了一個常量 someIntSet,該常量可以存儲 Integer 集,而無需顯式指定類型。但是,我們需要在定義變量時帶上 :Set,否則Swift將為我們創(chuàng)建一個數(shù)組。
此外,作為數(shù)組,我們使用[]括號用 1、2、3、4、5、6、7、8、9 值初始化了集合。
您已經(jīng)知道,當您嘗試使用 print(someIntSet) 將集合中的值打印輸出時,你會得到一個不同的順序,不同于在集合中您已經(jīng)定義的項目順序,因為它存儲值沒有定義的順序。因此,每次訪問順序時都會發(fā)生變化。
let someStrSet:Set = ["ab","bc","cd","de","ab"] print(someStrSet)
運行該程序時,輸出為:
["de", "ab", "cd", "bc"]
你已經(jīng)知道,當你試圖打印集合內(nèi)的值作為打印(someIntSet) ,在上面的程序中,我們在集合中定義了一個重復值 ab。還有。當我們嘗試使用 print (someStrSet)訪問集合內(nèi)的值時,重復值將自動從集合中刪除。因此,set 保證其中的唯一元素/值。
您還可以在Swift中使用自己的自定義 Hashable 類型聲明一個集合。
不能使用下標語法作為數(shù)組訪問集合的元素。 這是因為集合是無序的,并且沒有訪問元素的索引。
所以,您需要使用其方法和屬性 或 使用for-in循環(huán)來訪問集合。
var someStrSet:Set = ["ab", "bc", "cd", "de"] for val in someStrSet { print(val) }
運行該程序時,輸出為:
de ab cd bc
在上面的程序中,我們得到的val與集合中元素的順序不同,因為集合與數(shù)組不同,它們是無序的。
您還可以訪問集合的元素,直接從集合中移除值,如下所示:
var someStrSet:Set = ["ab", "bc", "cd", "de"] let someVal = someStrSet.remove("cd") print(someVal) print(someStrSet)
運行該程序時,輸出為:
Optional("cd") ["de", "ab", "bc"]
在上面的程序中,您可以看到 remove方法返回一個可選字符串。因此,建議您執(zhí)行以下可選處理。要了解有關可選的更多信息,請訪問Swift 可選。
var someStrSet:Set = ["ab", "bc", "cd", "de"] if let someVal = someStrSet.remove("cd") { print(someVal) print(someStrSet) } else { print("cannot find element to remove") }
運行該程序時,輸出為:
cd ["de", "ab", "bc"]
您可以使用Swift中的 insert() 方法將新元素添加到集合中。
var someStrSet:Set = ["ab", "bc", "cd", "de"] someStrSet.insert("ef") print(someStrSet)
運行該程序時,輸出為:
["ab", "de", "cd", "ef", "bc"]
在上面的程序中,我們使用集合的insert()方法向集合添加新元素。由于集合是無序的,因此插入元素的位置是未知的。
使用集合的另一個主要優(yōu)點是可以執(zhí)行集合操作,例如將兩個集合組合在一起、確定兩個集合具有哪些共同的值等。這些操作類似于數(shù)學中的集合操作。
兩個集合a和b的并集是在a或b中 或 在a和b兩者中的元素的集合。
let a: Set = [1, 3, 5, 7, 9] let b: Set = [0, 2, 4, 6, 8] print(a.union(b))
當您運行上述程序時,輸出將是:
[8, 2, 9, 4, 5, 7, 6, 3, 1, 0]
兩個集合a和b的交集是包含a的所有元素的集合,這些元素同時也屬于b。
let a: Set = [1, 3, 5, 7, 9] let b: Set = [0, 3, 7, 6, 8] print(a.intersection(b))
當您運行上述程序時,輸出將是:
[7, 3]
因此,print(a.intersection(b))輸出一個新的集合,其值 [7、3] 在 a 和 b 集合中都存在。
兩個集合a和b的差集,它包含 a 的所有元素,但去掉同樣屬于 b 的元素。
let a: Set = [1, 3, 5, 7, 9] let b: Set = [0, 3, 7, 6, 8] print(a.subtracting(b))
當您運行上述程序時,輸出將是:
[5, 9, 1]
因此,print(a.subtracting(b)) 輸出具有值[ 5,9,1] 的新集合。
兩個集合a和b的對稱差是包含所有元素的集合,這些元素位于兩個集合中的任何一個中,但不同時存在兩個集合中。
let a: Set = [1, 3, 5, 7, 9] let b: Set = [0, 3, 7, 6, 8] print(a.symmetricDifference(b))
當您運行上述程序時,輸出將是:
[5, 6, 8, 0, 1, 9]
因此,print(a.symmetricDifference(b)) 輸出具有值[ 5、6、8、0、1、9] 的新集合。
您可以使用 == 運算符檢查兩個集合是否包含相同的元素。如果兩個集合包含相同的元素,則返回true,否則返回false。
let a: Set = [1, 3, 5, 7, 9] let b: Set = [0, 3, 7, 6, 8] let c:Set = [9, 7, 3, 1, 5] if a == b { print("a和b相同") } else { print("a和b不同") } if a == c { print("a和c相同") } else { print("a和c不同") }
當您運行上述程序時,輸出將是:
a和b不同 a和c相同
您還可以使用以下方法檢查兩個集合之間的關系:
isSubset(of:) - 此方法確定一個集合的所有值是否都存在于指定的集合中。
isSuperset(of:) - 此方法確定集合是否包含指定集合中的所有值。
isStrictSubset(of:)或 isStrictSuperset(of:): - 此方法確定一個集合是指定集合的子集還是超集,但不等于指定集合。
isDisjoint(with:) - 此方法確定兩個集合是否沒有共同的值。
let a: Set = [1, 3, 5, 7, 9] let b: Set = [0, 3, 1, 7, 6, 8, 9, 5] print("isSubset:", a.isSubset(of: b)) print("isSuperset:", b.isSuperset(of: a)) print("isStrictSubset:", a.isStrictSubset(of: b)) print("isDisjointWith:", a.isDisjoint(with: b))
當您運行上述程序時,輸出將是:
isSubset: true isSuperset: true isStrictSubset: true isDisjointWith: false
讓我們分析下面的print語句中使用的方法:
isSubset返回 true,因為集合b包含a中的所有元素
isSuperset返回true,因為b包含a的所有值。
isStrictSubset返回true,因為集合b包含a中的所有元素,并且兩個集合不相等。
isDisjointWithreturns 返回 false,因為a和b具有一些共同的值。
此屬性確定集合是否為空。如果集合不包含任何值,它返回true,否則返回false。
let intSet:Set = [21, 34, 54, 12] print(intSet.isEmpty)
運行該程序時,輸出為:
false
此屬性用于訪問集合的第一個元素。
let intSet = [21, 34, 54, 12] print(intSet.first)
運行該程序時,輸出為:
Optional(54)
由于Set是無序集合,因此 first 屬性并不能保證是該集合的第一個元素。 您很有可能會得到54以外的其他值。
同樣,您可以使用 last 屬性來訪問集合的最后一個元素。
insert函數(shù)用于在集合中插入/追加元素。
var intSet:Set = [21, 34, 54, 12] intSet.insert(50) print(intSet)
運行該程序時,輸出為:
[54, 12, 50, 21, 34]
此函數(shù)以相反的順序返回集合的元素。
var intSet:Set = [21, 22, 23, 24, 25] print(intSet) let reversedSet = intSet.reversed() print(reversedSet)
運行該程序時,輸出為:
[22, 23, 21, 24, 25] [25, 24, 21, 23, 22]
此屬性返回集合中元素的總數(shù)。
let floatSet:Set = [10.2, 21.3, 32.0, 41.3] print(floatSet.count)
運行該程序時,輸出為:
4
此函數(shù)從集合中刪除并返回第一個值。
var strSet:Set = ["ab", "bc", "cd", "de"] let removedVal = strSet.removeFirst() print("removed value is \(removedVal)") print(strSet)
運行該程序時,輸出為:
removed value is de ["ab", "cd", "bc"]
同樣,您也可以使用 removeAll 函數(shù)來清空集合。