Sets
Set不知該怎麼翻譯@@。比如說麥當勞(要倒了)裡面的套餐,裡面就固定有一個漢堡,一份薯條,以及一杯飲料,這就叫做一個"Set"。
Set存放的是同型態但獨特的值,並且沒有順序性。若我們存取值的順序是不重要的,或是能保證裡面的值不會重覆,我們就可以用Set來代替Array。
Hash Values for Set Types
任何一個要放在Set裡的型態都必需是可以隨意放置的;也就是說,這個型態必需提供方法去計算自己的Hash Value(雜湊值)。Hash value的型態為Int,若是兩個物件比較的時候是相等的,也就是指他們的hash value是相等的,如:
if a == b 跟 if a.hashValue == b.hashValue
Swift所內建的一些基本型態都有hash value,如String, Int, Double等等。
Set Type Syntax
Type的寫法為Set<T>,且沒有簡易的寫法(Array才有)。
我們先產生一個空的Set
var letters = Set<Character>()
Set也可以用陣列的方式存值:
letters = ["a", "b", "c"] // letters = {a, b, c}
letters = [] //清空letters,且值的型態還是Character
我們也可在一開始宣告的時候直接使用陣列給值:
var genres: Set<String> = ["Rock", "Classical", "Hip hop"]
這是比較嚴謹的寫法,若我們固定了Set內的型態一定是要String,那麼就後面的[]裡就不能放其他東西。
由於Swift的自動型態判斷,我們也可以這樣寫:
var genres: Set = ["Rock", "Classical", "Hip hop"]
Accessing and Modifying a Set
我們有一些方法及屬性是跟陣列相同的:
print(genres.count) // print 3
if genres.isEmpty {
print("genres is empty")
} else {
print("genres has values")
}
// genres has values
genres.insert("Jazz")
// genres has four items now
Set的移除跟陣列不一樣的是,陣列是針對索引去移除,而由於Set沒有順序性,加上裡面的值都是唯一的,因此刪除方法即直接將內容寫入:
genres.remove("Rock")
由於值是唯一性,因此我們也可以利用contains(T)來判斷裡面是否有T這個東西:
if genres.contains("Funk") {
print("genres has Funk")
} else {
print("Funk isn't exist")
}
// Funk isn't exist
同樣的,也可以用for-in將值取出:
for genre in genres {
print(genres)
}
上述這些例子,裡面的值千萬不要有重覆,不然就會出問題。
寫到這裡,其實Set跟Array看起來也沒有太多差別。但Set真正強大的地方應該是接下來要講的部分:
performing Set Operations
事實上我們可以有效率的將兩個set合在一起,並依照需求,將兩個set裡相同/不同的部分做處理,來達成我們的目的。比如說,我們有兩組數字,分別為1, 2, 4, 5, 7, 9 及 2, 3, 6, 7, 8, 9。若是我們想要將這兩組合在一起並且不重覆,
變成1, 2 3, 4, 5, 6, 7, 8, 9,在傳統的程式裡就會寫得很辛苦了。我們要一個一個去比對,並存取還沒出現(未重覆)的數字。這樣的程式碼應該是要好幾行跑不掉。
在Set裡,我們可以使用內建的四個方法來處理類似的事情:
intersect:取兩個Set裡重覆的值。
exclusiveOr:取兩個Set不重覆的值。
union:取兩個Set全部的值但不會重復出現。
subtract:取第一個Set裡不跟第二個Set重覆的值。
剛剛的例子就可以用union來取,一行程式碼就解決了~
let oddDigits: Set = [1, 3, 5, 7, 9] //奇數
let eventDigits: Set = [0, 2, 4, 6, 8] //偶數
let primeNum: Set = [2, 3, 5, 7] //質數
oddDigits.union(evenDigits)
// union,取所有值但不重覆
//回傳[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
oddDigits.intersect(evenDigits)
// intersect,取重覆的值
//回傳[]
oddDigits.subtract(primeNum)
// subtract, 取第一個Set裡不跟第二個重覆的值
// 回傳 [1, 9]
oddDigits.exclusiveOr(primeNum)
// exclusiveOr,取兩個Set不重覆的值
// 回傳 [1, 2, 9]
*上述所提到的回傳,裡面的順序是不一定的,因為Set並沒有順序性。
除了合成外,我們也可以判斷兩個Set之間的關係:
a.isSubsetOf(b): 判斷a的所有內容是否都在b裡
a.isSupersetOf(b): 判斷a是否包含了所有b的內容
isStrictSubsetOf 以及 isStrictSupersetOf跟上面兩個一樣,只是a跟b不能是一樣的。(更嚴謹的判斷)
a.isDisjoinWith(b): 判斷a跟b有沒有重覆的內容
let houseAnimals: Set = ["Dog", "Cat"]
let farmAnimals: Set = ["Cow", "Chick", "Sheep", "Dog", "Cat"]
let cityAnimals: Set = ["Bird", "Mouse"]
houseAnimals.isSubsetOf(farmAnimals) // return true
farmAnimals.isSupersetOf(houseAnimals) // return true
farmAnimals.isDisjoinWith(cityAnimals) // return true
提醒,若a.isSubserOf(b)成立,那b.isSupersetOf(a)就一定成立喔。