** 這是我的集合系列文章的第一篇授嘀,計(jì)劃從淺入深通過(guò)一系列文章將swift的集合相關(guān)內(nèi)容徹底整理清楚物咳,包括集合類(lèi)相關(guān)的第三方代碼庫(kù),最后自定義一個(gè)集合類(lèi)型蹄皱,把所有的內(nèi)容用代碼貫穿起來(lái)览闰。**
Generators, Sequences 和 Collections 是swift標(biāo)準(zhǔn)庫(kù)的重要組成部分,也是我們編程過(guò)程中最常用到的內(nèi)容巷折,所以理解它們是如何工作的可以很好的提升我們的基本功压鉴。如果你能打開(kāi)playground運(yùn)行一下本文的代碼,那么會(huì)更好的下面的內(nèi)容盔几。
Generators
我們可以把Generators看做是生成器晴弃,它的作用就是提供下一個(gè)元素,如果沒(méi)有下一個(gè)元素則返回nil,標(biāo)識(shí)生產(chǎn)過(guò)程結(jié)束。從代碼層面看Generator封裝了迭代器的狀態(tài)以及迭代器接口上鞠。它通過(guò)提供一個(gè)叫做next()的方法來(lái)返回sequence中的下一個(gè)元素际邻。
我們可以通過(guò)實(shí)現(xiàn) GeneratorType 協(xié)議來(lái)獲得一個(gè) Generator,
protocol GeneratorType {
associatedtype Element
mutating func next() -> Element?
}
要實(shí)現(xiàn)這個(gè)協(xié)議我們要做的事情并不多,我們只需要讓next()方法返回下一個(gè)元素芍阎,并且在沒(méi)有元素的時(shí)候返回nil就可以了世曾。
import Foundation
func pow2(power: Int) -> Int {
return Int(pow(2.0, Double(power)))
}
struct PowersOfTwoGenerator1 : GeneratorType {
associatedtype Element = Int
var power : Int = 0
mutating func next() -> Element? {
return pow2(power++)
}
}
現(xiàn)在我們已經(jīng)成功的獲得了一個(gè) Generator,我們可以調(diào)用它了谴咸。
var n = 10
var g = PowersOfTwoGenerator1()
while n > 0 {
n -= 1
println(g.next()!)
}
我們只需要調(diào)用next()方法就可以源源不斷的獲得“下一個(gè)元素”了轮听,雖然很簡(jiǎn)單,但是有一些遺憾岭佳,我們只能通過(guò)外部的邏輯才能控制元素的個(gè)數(shù)(在while循環(huán)中控制 n
的個(gè)數(shù))血巍,現(xiàn)在我們計(jì)劃把這個(gè)工作交給 Generator 自己。
struct PowersOfTwoGenerator2 : GeneratorType {
associatedtype Element = Int
var power : Int = 0
let endPower : Int
init(end : Int) {
endPower = end
}
mutating func next() -> Element? {
return (power < endPower) ? pow2(power++) : nil
}
}
我們給 Generator 一個(gè)構(gòu)造器珊随,通過(guò)構(gòu)造器來(lái)設(shè)置一個(gè)停止生產(chǎn)元素的條件述寡。
var g2 = PowersOfTwoGenerator2(end:10)
while let x = g2.next() {
println(x)
}
只做了一個(gè)小改動(dòng),是不是讓調(diào)用代碼簡(jiǎn)潔了很多叶洞?
到這里我們可以看到鲫凶,一個(gè) Generator 能做的工作并不多,一但返回nil衩辟,Generator的工作就結(jié)束了螟炫。
Sequences
sequence首先是一個(gè)values的序列,它可以使用for in循環(huán)控制結(jié)構(gòu)進(jìn)行迭代艺晴。另一方面sequence是Generator的工廠類(lèi)昼钻,它知道如何生產(chǎn)一個(gè)適合的Generator。
我們可以通過(guò)實(shí)現(xiàn)SequenceType協(xié)議來(lái)獲得一個(gè)sequence财饥,這部分工作也不復(fù)雜换吧。
struct PowersOfTwoSequence2 : SequenceType {
associatedtype Generator = PowersOfTwoGenerator2
let endPower : Int
init(end: Int) {
self.endPower = end
}
func generate() -> Generator {
return Generator(end: self.endPower)
}
}
太棒了,我們現(xiàn)在已經(jīng)獲得一個(gè)sequence了钥星,快用for in遍歷一下試試沾瓦。
for x in PowersOfTwoSequence2(end:10) {
println(x)
}
雖然 PowersOfTwoSequence2 已經(jīng)可以工作了,但它的實(shí)現(xiàn)有一個(gè)遺憾谦炒,endPower這個(gè)屬性需要分別在 PowersOfTwoSequence2 與 PowersOfTwoGenerator2中初始化兩次贯莺,我們不能容忍一個(gè)屬性如此的放縱.
struct PowersOfTwoSequence4 : SequenceType {
let endPower : Int
init(end: Int) {
self.endPower = end
}
func generate() -> AnyGenerator<Int> {
var power : Int = 0
let nextClosure : () -> Int? = {
(power < self.endPower) ? pow2(power++) : nil
}
return AnyGenerator<Int>(nextClosure)
}
}
在這段代碼里,我們讓 generate() 返回一個(gè) AnyGenerator 宁改,AnyGenerator實(shí)現(xiàn)了 GeneratorType 協(xié)議缕探,并且可以通過(guò)閉包的方式來(lái)創(chuàng)建 next() 方法。我們創(chuàng)建一個(gè)閉包 nextClosure 并溝通構(gòu)造器傳遞個(gè) AnyGenerator 还蹲,從而完成了 Generator 的創(chuàng)建爹耗。因?yàn)殚]包幫助我們綁定了 endPower 耙考,所以我們解決了 之前屬性需要被初始化兩次的問(wèn)題。
我們可以通過(guò)尾閉包的方式潭兽,進(jìn)一步精簡(jiǎn)代碼倦始。
struct PowersOfTwoSequence5 : SequenceType {
let endPower : Int
init(end: Int) {
self.endPower = end
}
func generate() -> AnyGenerator<Int> {
var power : Int = 0
return AnyGenerator<Int> {
(power < self.endPower) ? pow2(power++) : nil
}
}
}
Collections
一個(gè) collection就是一個(gè)實(shí)現(xiàn)了 startIndex 和 endIndex 并且可以通過(guò)下標(biāo)(subscript)訪問(wèn)的sequence。collection比sequence更進(jìn)一步的做到了山卦,允許單個(gè)元素可以重復(fù)訪問(wèn)鞋邑。
集合協(xié)議擴(kuò)展了SequenceType。
public protocol CollectionType : Indexable, SequenceType {
public var startIndex: Self.Index { get }
public var endIndex: Self.Index { get }
public subscript (position: Self.Index) -> Self._Element { get }
}
實(shí)現(xiàn)一個(gè)集合協(xié)議的工作比實(shí)現(xiàn)一個(gè)SequenceType的工作稍微多一些账蓉。
struct PowersOfTwoCollection : CollectionType {
associatedtype Index = Int
let startIndex : Int
let endIndex : Int
init(start:Int, end: Int) {
self.startIndex = start
self.endIndex = end
}
func generate() -> AnyGenerator<Int> {
var power : Int = 0
return AnyGenerator<Int> {
(power < self.endIndex) ? pow2(power++) : nil
}
}
subscript(i: Index) -> Int { return pow2(i) }
}
我們?cè)?PowersOfTwoSequence5 的基礎(chǔ)很容實(shí)現(xiàn) CollectionType 協(xié)議枚碗。通過(guò)構(gòu)造函數(shù),為collection初始化 startIndex 與 endIndex铸本。提供subscript來(lái)為collection提供下標(biāo)訪問(wèn)的能力“褂辏現(xiàn)在我們擁有一個(gè)集合了。
for x in reverse(PowersOfTwoCollection(start:0,end:10)) {
println(x)
}
關(guān)于集合归敬,這里只是剛剛開(kāi)始酷含,如果大家希望了解更多的集合內(nèi)容,歡迎大家關(guān)注我后面的更新汪茧。我正在深入的研究swift語(yǔ)言,并將我的學(xué)習(xí)內(nèi)容不斷的總結(jié)出來(lái)限番,希望能和大家交流共同進(jìn)步舱污。