上一篇提到了第一格 Collection Type:Array,是一個有順序性的集合,所以你可以使用 index 來檢索你要的資料,但是第二部曲要來介紹的是無順序的集合,Set。
Set 跟 Array 很相似,一樣都只允許存放同型別的資料,但差別就在於 Set 是沒有順序性的,在取用上相對於 Array 就不是這麼容易,所以要使用 Set 的前提,最好確保儲存的資料是不會被頻繁的來取用,否則使用 Array 會是比較適合,接下來我們就來看 Set 的特性及使用方式吧!
Set 的宣告方式跟 Array 幾乎是一模一樣,可以用 Set<element>
來宣告一個 Set。
var 套餐A: Set<String> = []
var 套餐B: Set<String> = ["乾麵", "魚丸湯", "燙青菜"]
套餐A = ["乾麵", "魚丸湯"]
print(套餐A) // ["魚丸湯", "乾麵"]
print(套餐B) // ["魚丸湯", "乾麵", "燙青菜"]
但是 Set 跟 Array 的語法都是以 []
的方式來實作,所以如果在宣告的時候不特別註記型別直接指派初始值,在型別推論預設會推論為 Array 喔!
var 套餐C = ["炒飯", "貢丸湯"]
print("套餐C 的型別為 \(type(of: 套餐C))")
// 套餐C 的型別為 Array<String>
但是 Set 不能像 Array 一樣直接使用 [element]
來宣告,因為這樣宣告,也會被推論為 Array。
var 套餐D: [String] = ["炒飯", "中杯紅茶"]
print("套餐D 的型別為 \(type(of: 套餐D))")
// 套餐D 的型別為 Array<String>
這裡來介紹兩種方式來加入 element 到 Set 中,element 必須與 Set 中的值型態相符:
insert(_ newMember: element)
update(with newMember: element)
這兩個 methods 都可以加入新的 element 到 Set 裡,但是他們終究還是有些許差別,我們來看看這兩位同學在官方 API 是怎樣被描述的 ( insert(_:)、update(with:) ),可以發現到 insert 再加入新的 element 前,會先要檢查是否存在於 Set 中;update 則會無條件的加入,把舊有的 element 取代掉。
var exampleSet: Set = [1, 2, 3]
print(exampleSet.insert(4))
print(exampleSet.insert(4))
print(exampleSet.update(with: 5))
print(exampleSet.update(with: 5))
print(exampleSet)
/*
Prints:
(inserted: true, memberAfterInsert: 4)
(inserted: false, memberAfterInsert: 4)
nil
Optional(5)
[2, 1, 4, 5, 3]
*/
我是誰?我在哪?
讓我們來一起看看上面發生什麼事情,在這之前我們來回顧一下這兩個方法似乎都有回傳值:
insert(_ newMember: element)
這個方法會回傳一組 tuple:(inserted: Bool, memberAfterInsert: Element)
,當 newMember 不存在於 Set 中,就會加入新的 element,然而inserted 會回傳 true
、memberAfterInsert 會回傳 newMember
;反之則是 false
以及 oldMember
,並且不會加入新 element。update(with newMember: element)
這個方法會回傳一個 Optional element,當 newMember 不存在於 Set 中,會回傳 nil
;要不然就會回傳一個 Optional(newMember)
。如果想要移除 Set 某個 element,可以像是 Array 使用 remove
,但是使用的方式有點不太一樣的地方是,Array 在使用 remove 需要帶入 index 值,但是 Set 是一個無序排列,可以 Print 看看你會發現,每一次 Set 的排列都會不一樣,那在 Set 要怎麼使用 remove 呢?來看看 Set 的實體方法:
remove(_ member: Element) -> Element?
這個方法需要帶入 Element,然而這個在移除之前,會先檢查 Element 是否存在於 Set 中,如果存在就移除掉,然後回除一個 Optional(element)
,如果找不到的話就只會回傳 nil,而且既然找不到 element,所以也就沒什麼移不移除的需求了。
var exampleSet: Set = [1, 2, 3]
print(example.remove(1)) // prints Optional(1); exampleSet 現在只剩 [2, 3]
print(example.remove(4)) // prints nil; exampleSet 還是只剩 [2, 3]
Set 與 Array 一樣,都實作了 Collection Protocol,所以也可以使用 for...in loop
走訪每個 Element~
let stringSet: Set = ["A", "B", "C", "D"]
for element in StringSet {
print(element)
}
同理你也可以使用上一篇介紹 contains、isEmpty 以及 count。
最主要來介紹 Set 比較常用的方法,還記得集合之間的關係比較吧,讓我們來回憶一下:
我們來看個官方的圖就比較清楚一點~
所以如果以所以如果以程式碼表示就會像是這樣:
let aSet: Set = [1, 3, 5, 7, 9, 2]
let bSet: Set = [1, 5, 9, 6]
aSet.intersection(bSet).sorted()
// [1, 5, 9]
aSet.union(bSet).sorted()
// [1, 2, 3, 5, 6, 7, 9]
aSet.subtracting(bSet).sorted()
// [2, 3, 7]
aSet.symmetricDifference(bSet).sorted()
// [2, 3, 6, 7]