Swift 初學(xué)者 ( 12/12 ) 集合

簡(jiǎn)介

這是一個(gè)Swift語(yǔ)言教程,基于最新的iOS 9,Xcode 7.3和Swift 2.2,會(huì)為你介紹Swift編程非常基礎(chǔ)的內(nèi)容。從電腦如何工作的全程基本原理到語(yǔ)言結(jié)構(gòu),你會(huì)足夠了解這門(mén)語(yǔ)言,來(lái)處理數(shù)據(jù)和管理代碼的行為。

快速鏈接


集合

集合(set)是沒(méi)有順序的相同類(lèi)型唯一值的集合。當(dāng)你想確保一個(gè)項(xiàng)目不會(huì)在集合里出現(xiàn)多次的時(shí)候,它會(huì)變得非常有用,并且項(xiàng)目的順序并不重要。

例如,你想追蹤游戲里還有哪些選手是活躍的,就可以用集合。

你對(duì)于這里選手的順序并不感興趣;你想讓集合做的事是存儲(chǔ)人并且并不允許他們?cè)诩侠锍霈F(xiàn)兩次。然后只需要問(wèn)集合,“Alice 還在游戲里嗎?”然后預(yù)期得到一個(gè)布爾型的 true / false。

如上圖所示,沒(méi)有索引或鍵可以用來(lái)取回值。你會(huì)在這篇文章里讀到,你仍然可以遍歷集合以及查詢(xún)特定的值在不在集合里。

創(chuàng)建集合

你可以顯示聲明集合,通過(guò)寫(xiě) Set 緊接著尖括號(hào)里加上類(lèi)型:

let setOne: Set<Int>

Swift 也能從初始化的類(lèi)型里推斷集合的類(lèi)型:

let setTwo = Set<Int>()

打印 setTwo,你會(huì)發(fā)現(xiàn)有趣的東西:

print(setTwo)
// > []

它顯示了空的集合字面值和空數(shù)組的相同。

集合字面值

數(shù)組和集合不只是空的字面值相同。事實(shí)上,集合沒(méi)有自己的字面值,用數(shù)組字面值來(lái)創(chuàng)建帶有初始值的集合??催@個(gè)例子:

let someArray = [1, 2, 3, 1]

這是一個(gè)數(shù)組。那怎么用數(shù)組字面值創(chuàng)建集合呢?像這樣:

let someSet: Set<Int> = [1, 2, 3, 1]

你需要顯示聲明變量為一個(gè) Set。但是,感謝 Swift 的類(lèi)型推斷,你可以忽略集合包含的值類(lèi)型:

let anotherSet: Set = [1, 2, 3, 1]

很明顯,這是整數(shù)集合,所以不需要定義集合的類(lèi)型。

要用行動(dòng)看一下集合最重要的特色,讓我們打印一下你剛剛創(chuàng)建的集合:

print(someSet)
// > [2, 3, 1]

首先,可以看到?jīng)]有特定的順序。其次,盡管你創(chuàng)建的集合帶有兩個(gè)實(shí)例值為 1,但這個(gè)值只出現(xiàn)了一次——記住,集合的值必須是唯一的。

訪問(wèn)元素

集合里的元素沒(méi)有索引或鍵,所以你怎么知道集合到底有沒(méi)有元素呢,以及怎么訪問(wèn)它擁有的任意元素?就像數(shù)組和字典,集合支持 count 和 isEmpty properties。

print(someSet.isEmpty)
// > false
print(someSet.count)
// > 3

可以使用 contains(_:) 來(lái)檢查特定元素是否存在:

print(someSet.contains(1))
// > true
print(someSet.contains(4))
// > false

你也可以使用 first 和 last properties,返回集合里的一個(gè)元素。但是,因?yàn)榧蠜](méi)有順序,你無(wú)法確切知道會(huì)獲得哪個(gè)項(xiàng)目。盡管對(duì)于尺寸為 0 或 1 的集合,這會(huì)是一個(gè)獲取單一集合元素的快捷方式。

print(someSet.first)
// > Optional(2)

就像預(yù)料的,frist 返回了可選值。它必須這樣做因?yàn)榧峡赡苁强盏模谶@種情況下 property 會(huì)返回 nil。

添加和移除元素

回到紙牌游戲。你想為明天規(guī)劃一個(gè)游戲,希望選擇一個(gè)對(duì)所有人對(duì)方便的時(shí)間。從建議你自己的適宜時(shí)間開(kāi)始:

var myTimes: Set = ["8am", "9am", "10am"]

你把這個(gè)集合聲明為變量,因?yàn)槠每赡軙?huì)改變。例如,假設(shè)你決定上午 11 點(diǎn)也是開(kāi)始游戲的耗時(shí)間,那就給集合添加另一個(gè)元素:

myTimes.insert("11am")
print(myTimes)
// > ["9am", "8am", "11am", "10am"]

insert(_:) 添加了元素到集合;如果元素已經(jīng)存在,方法什么都不會(huì)做。

你意識(shí)到上午 8 點(diǎn)太早了。你可以像這樣從集合里移除元素:

let removedElement = myTimes.remove("8am")
print(removedElement)
// > Optional("8am")

remove(_:) 返回被移除的元素,如果它在集合里的話,否則就是 nil。

迷你練習(xí)

寫(xiě)一個(gè)函數(shù)移除整數(shù)數(shù)組里的所有重復(fù)。數(shù)組?你想問(wèn)這篇不是關(guān)于集合的嗎?

小提示:數(shù)組有一個(gè)用 Set 類(lèi)型的初始化,集合有一個(gè)用 Array 類(lèi)型的初始化。

遍歷集合

當(dāng)你想遍歷集合的元素的時(shí)候用 for-in 循環(huán):

for element in myTimes {
    print(element)
}
// > 9am
// > 11am
// > 10am

可以預(yù)料,結(jié)果沒(méi)有預(yù)先設(shè)置的順序。然而,這和你在其它集合類(lèi)型里看到的 for-in 語(yǔ)法相似。

集合操作

集合最強(qiáng)大的特色之一就是他們支持集合操作(set operations),允許你把兩個(gè)集合組成一個(gè),創(chuàng)建只有兩個(gè)或更多集合的共同值的集合。讓我們用你的偏好時(shí)間集合來(lái)檢測(cè)這些操作,以及另一組時(shí)間。

提醒一下,你提議了游戲時(shí)間為上午 9 點(diǎn),10 點(diǎn)或 11 點(diǎn)。Adam 給你發(fā)送了他的偏好時(shí)間:

let adamTimes: Set = ["9am", "11am", "1pm"]

讓我們依次看看集合操作的四個(gè)類(lèi)型。

Union

union(_:) 創(chuàng)建新集合,帶有兩個(gè)集合所有的值:

let unionSet = myTimes.union(adamTimes)
print(unionSet)
// > ["9am", "11am", "10am", "1pm"]

主要要注意盡管你和 Adam 都選擇了上午 9 點(diǎn) 和 上午 11 點(diǎn)為見(jiàn)面好時(shí)間,這些值在新集合只出現(xiàn)了一次。

這里,你留下了你和 Adam 提議的每個(gè)時(shí)間。

Intersect

intersect(_:) 創(chuàng)建新集合,只帶有兩個(gè)集合的共同值。你可以用它創(chuàng)建基于你和 Adam 同意的時(shí)間集合。

let intersectSet = myTimes.intersect(adamTimes)
print(intersectSet)
// > ["9am", "11am"]

這里,結(jié)果集合里的值就是在 myTimes 和 adamTimes 集合里同時(shí)出現(xiàn)的那些。

Subtract

subtract(_:) 創(chuàng)建新集合,移除在第二個(gè)集合里出現(xiàn)的值。

let subtractSet = myTimes.subtract(adamTimes)
print(subtractSet)
// > ["10am"]

從 myTimes 里的所有時(shí)間開(kāi)始。然后 subtract(:_) 移除了 adamTimes 里出現(xiàn)的所有時(shí)間,留下只有你提議、Adam 沒(méi)有提議的時(shí)間。

這個(gè)例子里,上午 10 點(diǎn)是唯一的你提議但沒(méi)有被 Adam 也提議的時(shí)間。

Exclusive Or

exclusiveOr(_:) 創(chuàng)建新集合,帶有只在一個(gè)集合出現(xiàn)的值,不包括同時(shí)具有的。

let exclusiveOrSet = myTimes.exclusiveOr(adamTimes)
print(exclusiveOrSet)
// > ["10am", "1pm"]

這些是你提議但 Adam 沒(méi)有提議的開(kāi)始時(shí)間,以及 Adam 提議而你沒(méi)有的開(kāi)始時(shí)間。

迷你練習(xí)

快速回答:你會(huì)用哪個(gè)集合操作來(lái)找到見(jiàn)面的合適時(shí)間?

集合操作的運(yùn)行時(shí)間

集合和字典有非常相似的實(shí)現(xiàn),他們也需要元素可以被哈希。所有操作的運(yùn)行時(shí)間都和字典的那些相同。

關(guān)鍵點(diǎn)

  • 集合(Sets)是相同類(lèi)型的唯一值的無(wú)序集合。
  • 集合在你需要知道一些東西是不是被包含在集合里的時(shí)候最有用處。
  • 可以從數(shù)組初始化集合,反之亦然。
  • 集合操作(Set operations)很強(qiáng)力,允許你處理潛在的大量數(shù)據(jù)來(lái)組合和過(guò)濾元素。

接下來(lái)去哪兒?

既然你現(xiàn)在已經(jīng)學(xué)習(xí)了 Swift 里的三種集合類(lèi)型,你應(yīng)該很了解他們能做什么以及何時(shí)該使用它們。你在繼續(xù)讀教程的時(shí)候會(huì)看到出現(xiàn)。

現(xiàn)在你知道怎么把數(shù)組組合進(jìn)數(shù)組、字典和集合里了,本教程的下一個(gè)部分涉及了命名類(lèi)型(named types)。他們?cè)试S你同時(shí)組合數(shù)據(jù)和代碼到一起,放到自定義的類(lèi)型里,作為更大和更好的東西的建筑塊!

移步之前,看看下面的挑戰(zhàn)來(lái)測(cè)試你的集合知識(shí)。

挑戰(zhàn)

挑戰(zhàn) A:你就是編譯器

下列哪個(gè)為有效語(yǔ)句?

1. let set1: Set<Int> = [1]
2. let set2 = [1]
3. let set3 = Set<Int>()

對(duì)于接下來(lái)的三條語(yǔ)句,使用這個(gè)集合:

let set4: Set = [1, 2, 3]

4. set4[1]
5. set4.insert(1)
6. set4.contains(1)

對(duì)于接下來(lái)的兩條語(yǔ)句,使用這個(gè)集合:

var set5: Set = [1, 2, 3]

7. set5.insert("1")
8. set5.remove(1)

挑戰(zhàn) B:檢測(cè)集合包含的項(xiàng)目

假設(shè)你有 10,000 個(gè)人的郵箱地址集合:let emails: Set<String>。寫(xiě)一個(gè)函數(shù),如果給定的郵箱地址在集合里就返回 true,否則 false。不允許用 contains(_:) 或遍歷集合。

挑戰(zhàn) C:追蹤到場(chǎng)人數(shù)

你是 Swift 大學(xué)里的教授,在教一個(gè)為期三天的課程。每天,你追蹤到場(chǎng)人數(shù),通過(guò)到場(chǎng)的每個(gè)學(xué)生的名字到新的集合里。

例如:

let day1: Set = ["Anna", "Benny", "Charlie"]
let day2: Set = ["Anna", "Benny", "Danny"]
let day3: Set = ["Anna", "Danny", "Eric"]
  1. 寫(xiě)一個(gè)函數(shù),返回三天都到了的學(xué)生的集合。
  2. 寫(xiě)一個(gè)函數(shù)判斷誰(shuí)在課程的第一天之后退出了。

這兩個(gè)函數(shù)的結(jié)構(gòu)為:

func funcName(day1: Set<String>, day2: Set<String>, day3: Set<String>) ->Set<String>

挑戰(zhàn)和迷你練習(xí)源代碼

https://yunpan.cn/cMQMgQ3itt7fy (提取碼:6680)


介紹

歡迎來(lái)到Swift世界!Swift是一門(mén)蘋(píng)果在2014年夏天發(fā)布的編程語(yǔ)言。從那之后,Swift發(fā)布了一個(gè)主要的版本跳躍,成為了開(kāi)始在蘋(píng)果平臺(tái):iOS,OS X,watchOS和tvOS開(kāi)發(fā)的最簡(jiǎn)單的方式。

誰(shuí)適合這篇教程

這篇教程適合懂一點(diǎn)編程、并且希望學(xué)習(xí)Swift的人。也許你已經(jīng)為網(wǎng)站寫(xiě)過(guò)一些JavaScript代碼,或者用Python寫(xiě)過(guò)一些簡(jiǎn)短的程序。這篇教程就是為你準(zhǔn)備的!你會(huì)學(xué)習(xí)到編程的基本概念,同時(shí)也會(huì)成為Swift語(yǔ)言小能手。

如果你是赤裸裸的編程新手,這篇教程也是為你準(zhǔn)備的!教程里貫穿有簡(jiǎn)短的鍛煉和挑戰(zhàn)來(lái)給你一些編程練習(xí),同時(shí)測(cè)試你的知識(shí)。

需要準(zhǔn)備什么

要看這篇教程,你需要準(zhǔn)備如下的東西:

  • 一臺(tái)運(yùn)行OS X El Captian(10.11)的Mac,帶有最新發(fā)布的更新并且安裝了安全補(bǔ)丁。這樣你才能夠安裝需要的開(kāi)發(fā)工具:最新版本的Xcode。
  • Xcode 7.3 或更新的版本。Xcode是用Swift寫(xiě)代碼的主要開(kāi)發(fā)工具。最小也需要Xcode 7.3版本,因?yàn)槟莻€(gè)版本包含Swift 2.2。你可以免費(fèi)從Mac App Store下載Xcode的最新版本,這里:http://apple.co/1FLn51R。

如果你還沒(méi)有安裝Xcode最新版本,在繼續(xù)看下面的教程前要確定安裝。

如何使用這篇教程

每篇教程都會(huì)介紹觸手可及的話題理論,伴隨大量Swift代碼來(lái)示范在學(xué)習(xí)的實(shí)際的應(yīng)用程序。

教程里的所有代碼都是平臺(tái)中立的;這意味著不是為iOS、OS X或任何其它平臺(tái)而特定。代碼在playgrounds里運(yùn)行,你在本篇中已經(jīng)學(xué)習(xí)了。

在剩下的教程里,你可以把代碼在自己的playground里輸入進(jìn)去。這樣你就可以和代碼“玩耍”(play around),做一些改變立即就能看見(jiàn)代碼運(yùn)行的結(jié)果。

剩下的教程里會(huì)貫穿實(shí)際小練習(xí),都是簡(jiǎn)短的練習(xí),關(guān)于觸手可及的主題。每篇的末尾也有挑戰(zhàn),會(huì)有編程問(wèn)題也會(huì)有長(zhǎng)一點(diǎn)的代碼練習(xí)來(lái)測(cè)試你的知識(shí)。做完就能掌握大部分的Swift基礎(chǔ)知識(shí)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容