徹底搞定集合之:Generators vs Sequences vs Collections

** 這是我的集合系列文章的第一篇授嘀,計(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)步舱污。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市弥虐,隨后出現(xiàn)的幾起案子扩灯,更是在濱河造成了極大的恐慌,老刑警劉巖霜瘪,帶你破解...
    沈念sama閱讀 219,110評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件珠插,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡颖对,警方通過(guò)查閱死者的電腦和手機(jī)捻撑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)缤底,“玉大人顾患,你說(shuō)我怎么就攤上這事「鲞螅” “怎么了江解?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,474評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)徙歼。 經(jīng)常有香客問(wèn)我犁河,道長(zhǎng)鳖枕,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,881評(píng)論 1 295
  • 正文 為了忘掉前任桨螺,我火速辦了婚禮耕魄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘彭谁。我一直安慰自己吸奴,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,902評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布缠局。 她就那樣靜靜地躺著则奥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪狭园。 梳的紋絲不亂的頭發(fā)上读处,一...
    開(kāi)封第一講書(shū)人閱讀 51,698評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音唱矛,去河邊找鬼罚舱。 笑死,一個(gè)胖子當(dāng)著我的面吹牛绎谦,可吹牛的內(nèi)容都是我干的管闷。 我是一名探鬼主播,決...
    沈念sama閱讀 40,418評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼窃肠,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼包个!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起冤留,我...
    開(kāi)封第一講書(shū)人閱讀 39,332評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤碧囊,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后纤怒,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體糯而,經(jīng)...
    沈念sama閱讀 45,796評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,968評(píng)論 3 337
  • 正文 我和宋清朗相戀三年泊窘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了熄驼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,110評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡州既,死狀恐怖谜洽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情吴叶,我是刑警寧澤阐虚,帶...
    沈念sama閱讀 35,792評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站蚌卤,受9級(jí)特大地震影響实束,放射性物質(zhì)發(fā)生泄漏奥秆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,455評(píng)論 3 331
  • 文/蒙蒙 一咸灿、第九天 我趴在偏房一處隱蔽的房頂上張望构订。 院中可真熱鬧,春花似錦避矢、人聲如沸悼瘾。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,003評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)亥宿。三九已至,卻和暖如春砂沛,著一層夾襖步出監(jiān)牢的瞬間烫扼,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,130評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工碍庵, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留映企,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,348評(píng)論 3 373
  • 正文 我出身青樓静浴,卻偏偏與公主長(zhǎng)得像堰氓,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子马绝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,047評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 從三月份找實(shí)習(xí)到現(xiàn)在豆赏,面了一些公司,掛了不少富稻,但最終還是拿到小米、百度白胀、阿里椭赋、京東、新浪或杠、CVTE哪怔、樂(lè)視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,253評(píng)論 11 349
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,178評(píng)論 25 707
  • 我的表妹小喬,人如其名向抢,略有幾分姿色认境,喜古風(fēng)、愛(ài)繪畫(huà)挟鸠,自視清高叉信,凡夫俗子皆不入眼,年近三十仍形單影只艘希,近日發(fā)表一通...
    亦花閱讀 760評(píng)論 5 3
  • 今天是端午節(jié)硼身,天好陰硅急,斷續(xù)下著雨,是在紀(jì)念屈原嗎佳遂?我一個(gè)人在屋里营袜,從昨晚開(kāi)始到現(xiàn)在,沒(méi)有飯吃丑罪,沒(méi)人說(shuō)話(huà)荚板,就這么過(guò)了
    擺好pose很重要閱讀 282評(píng)論 0 0
  • 晚上,B妹子和同學(xué)打電話(huà)吩屹,提到了這個(gè)年紀(jì)最該談?wù)摰脑?huà)題-戀愛(ài)與婚姻跪另。 “沒(méi)時(shí)間啊,而且我還是一個(gè)顏控祟峦,長(zhǎng)得好看的又...
    伍藝邇閱讀 280評(píng)論 0 0