Swift之集合型別 (Collection Types)(集合篇)

weixin_33782386發表於2017-12-20

集合(Sets)

集合(Set)用來儲存相同型別並且沒有確定順序的值。當 合元素順序不重要時或者希望確保每個元素只出現一次 時可以使用 合而不是陣列。
注意:Swift的 Set 型別被橋接到 Foundation 中的 NSSet 類。

集合型別的雜湊值
一個型別為了儲存在 集合中,該型別必須是可雜湊化的--也就是說,該型別必須提供一個方法來計算它的雜湊 值。一個雜湊值是 Int 型別的,相等的物件雜湊值必須相同,比如 a==b,因此必須 a.hashValue == b.hashValu e

Swift的所有基本型別(比如 String,Int , DoubleBool)預設都是可雜湊化的,可以作為 合的值的型別或 者字典的鍵的型別。沒有關聯值的列舉成員值(在列舉有講述)預設也是可雜湊化的。

合型別語法

Swift 中的 Set 型別被寫為Set<Element> ,這裡的 Element 表示 Set中允許儲存的型別,和陣列不同的是, 合沒有等價的簡化形式。

建立和構造一個空的 集合

var letters = Set<Character>()
print("letters is of type Set<Character> with \(letters.count) items.") // 列印 "letters is of type Set<Character> with 0 items."

注意:通過構造器,這裡的 letters 變數的型別被推斷為 Set<Character> 。

此外,如果上下文提供了型別資訊,比如作為函式的引數或者已知型別的變數或常量,我們可以通過一個空的數 組字面量建立一個空的 Set :

letters.insert("a")
// letters 現在含有1個 Character 型別的值
letters = []
// letters 現在是一個空的 Set, 但是它依然是 Set<Character> 型別

用陣列字面量建立集合

你可以使用陣列字面量來構造 合,並且可以使用簡化形式寫一個或者多個值作為 合元素。
下面的例子建立一個稱之為favoriteGenres 的 合來儲存 String型別的值:

var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"] 
// favoriteGenres 被構造成含有三個初始值的 集合

這個favoriteGenres變數被宣告為“一個 String值的 合”,寫為 Set<String>。由於這個特定的 合含有指 定 String 型別的值,所以它只允許儲存 String型別值。這裡的 favoriteGenres變數有三個 String 型別的初始 值("Rock""Classical""Hip hop" ),並以陣列字面量的方式出現。

注意: favoriteGenres 被宣告為一個變數(擁有 var 標示符)而不是一個常量(擁有 let 標示符),因為它裡面的元素將 會在下面的例子中被增加或者移除。

一個 Set 型別不能從陣列字面量中被單獨推斷出來,因此Set 型別必須顯式宣告。然而,由於 Swift 的型別推 斷功能,如果你想使用一個陣列字面量構造一個Set 並且該陣列字面量中的所有元素型別相同,那麼你無須寫出
Set 的具體型別。 favoriteGenres 的構造形式可以採用簡化的方式代替:

var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"]

由於陣列字面量中的所有元素型別相同,Swift可以推斷出 Set<String> 作為 favoriteGenres變數的正確型別。

訪問和修改一個集合
你可以通過 Set 的屬性和方法來訪問和修改一個 Set

為了找出一個Set 中元素的數量,可以使用其只讀屬性count :

print("I have \(favoriteGenres.count) favorite music genres.") // 列印 "I have 3 favorite music genres.

使用布林屬性 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."

你可以通過呼叫 Setinsert(_:)方法來新增一個新元素:

favoriteGenres.insert("Jazz")
// favoriteGenres 現在包含4個元素

你可以通過呼叫 Setremove(_:)方法去刪除一個元素,如果該值是該 Set的一個元素則刪除該元素並且返回 被刪除的元素值,否則如果該Set 不包含該值,則返回 nil 。另外, Set 中的所有元素可以通過它的removeAl l()方法刪除。

 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 中是否包含一個特定的值:

遍歷一個集合

你可以在一個for-in迴圈中遍歷一個 Set中的所有值。

 for genre in favoriteGenres {
     print("\(genre)")
 }
 // Classical
 // Jazz
 // Hip hop

SwiftSet型別沒有確定的順序,為了按照特定順序來遍歷一個 Set 中的值可以使用 sorted() 方法,它將返
回一個有序陣列,這個陣列的元素排列順序由操作符'<'對元素進行比較的結果來確定.

 for genre in favoriteGenres.sorted() {
     print("(genre)")
 }
 // prints "Classical"
 // prints "Hip hop"
 // prints "Jazz

集合操作

你可以高效地完成 Set 的一些基本操作,比如把兩個 集合組合到一起,判斷兩個 合共有元素,或者判斷兩個 集合是否全包含,部分包含或者不相交。

基本集合操作
• 使用 intersection(:) 方法根據兩個 閤中都包含的值建立的一個新的 集合。
• 使用 symmetricDifference(
:) 方法根據在一個 集合中但不在兩個 閤中的值建立一個新的 集合。 • 使用 union(:) 方法根據兩個集合的值建立一個新的集 合。
• 使用 subtracting(
:) 方法根據不在該 閤中的值建立一個新的 集合。

 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).sort()
 // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 oddDigits. intersection(evenDigits).sorted()
 // []
 oddDigits.subtracting(singleDigitPrimeNumbers).sorted()
 // [1, 9]  以 singleDigitPrimeNumbers集合為標準,取出oddDigits集合中不在singleDigitPrimeNumbers的值
 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
 farmAnimals.isDisjoint(with: cityAnimals)
 // true

相關文章