close

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)就一定成立喔。

arrow
arrow
    全站熱搜

    Eason 發表在 痞客邦 留言(0) 人氣()