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

** 這是我的集合系列文章的第一篇,計劃從淺入深通過一系列文章將swift的集合相關內容徹底整理清楚,包括集合類相關的第三方代碼庫,最后自定義一個集合類型,把所有的內容用代碼貫穿起來。**

Generators, Sequences 和 Collections 是swift標準庫的重要組成部分,也是我們編程過程中最常用到的內容,所以理解它們是如何工作的可以很好的提升我們的基本功。如果你能打開playground運行一下本文的代碼,那么會更好的下面的內容。

Generators

我們可以把Generators看做是生成器,它的作用就是提供下一個元素,如果沒有下一個元素則返回nil,標識生產過程結束。從代碼層面看Generator封裝了迭代器的狀態以及迭代器接口。它通過提供一個叫做next()的方法來返回sequence中的下一個元素。

我們可以通過實現 GeneratorType 協議來獲得一個 Generator,

protocol GeneratorType {
 associatedtype Element
  mutating func next() -> Element?
}

要實現這個協議我們要做的事情并不多,我們只需要讓next()方法返回下一個元素,并且在沒有元素的時候返回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++)
    }
}

現在我們已經成功的獲得了一個 Generator,我們可以調用它了。

var n = 10
var g = PowersOfTwoGenerator1()
while n > 0 {
  n -= 1
  println(g.next()!)
}

我們只需要調用next()方法就可以源源不斷的獲得“下一個元素”了,雖然很簡單,但是有一些遺憾,我們只能通過外部的邏輯才能控制元素的個數(在while循環中控制 n
的個數),現在我們計劃把這個工作交給 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 一個構造器,通過構造器來設置一個停止生產元素的條件。

var g2 = PowersOfTwoGenerator2(end:10)
while let x = g2.next() {
    println(x)
}

只做了一個小改動,是不是讓調用代碼簡潔了很多?

到這里我們可以看到,一個 Generator 能做的工作并不多,一但返回nil,Generator的工作就結束了。

Sequences

sequence首先是一個values的序列,它可以使用for in循環控制結構進行迭代。另一方面sequence是Generator的工廠類,它知道如何生產一個適合的Generator。

我們可以通過實現SequenceType協議來獲得一個sequence,這部分工作也不復雜。

struct PowersOfTwoSequence2 : SequenceType {
    associatedtype Generator = PowersOfTwoGenerator2
    let endPower : Int
    init(end: Int) {
        self.endPower = end
    }
    func generate() -> Generator {
        return Generator(end: self.endPower)
    }
}

太棒了,我們現在已經獲得一個sequence了,快用for in遍歷一下試試。

for x in PowersOfTwoSequence2(end:10) {
    println(x)
}

雖然 PowersOfTwoSequence2 已經可以工作了,但它的實現有一個遺憾,endPower這個屬性需要分別在 PowersOfTwoSequence2 與 PowersOfTwoGenerator2中初始化兩次,我們不能容忍一個屬性如此的放縱.

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() 返回一個 AnyGenerator ,AnyGenerator實現了 GeneratorType 協議,并且可以通過閉包的方式來創建 next() 方法。我們創建一個閉包 nextClosure 并溝通構造器傳遞個 AnyGenerator ,從而完成了 Generator 的創建。因為閉包幫助我們綁定了 endPower ,所以我們解決了 之前屬性需要被初始化兩次的問題。

我們可以通過尾閉包的方式,進一步精簡代碼。

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

一個 collection就是一個實現了 startIndex 和 endIndex 并且可以通過下標(subscript)訪問的sequence。collection比sequence更進一步的做到了,允許單個元素可以重復訪問。

集合協議擴展了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 }
}

實現一個集合協議的工作比實現一個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) }
}

我們在 PowersOfTwoSequence5 的基礎很容實現 CollectionType 協議。通過構造函數,為collection初始化 startIndex 與 endIndex。提供subscript來為collection提供下標訪問的能力。現在我們擁有一個集合了。

for x in reverse(PowersOfTwoCollection(start:0,end:10)) {
    println(x)
}

關于集合,這里只是剛剛開始,如果大家希望了解更多的集合內容,歡迎大家關注我后面的更新。我正在深入的研究swift語言,并將我的學習內容不斷的總結出來,希望能和大家交流共同進步。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,443評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,530評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,407評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,981評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,759評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,204評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,263評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,415評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,955評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,650評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,892評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,675評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,967評論 2 374

推薦閱讀更多精彩內容

  • 從三月份找實習到現在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發崗...
    時芥藍閱讀 42,320評論 11 349
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,659評論 25 708
  • 我的表妹小喬,人如其名,略有幾分姿色,喜古風、愛繪畫,自視清高,凡夫俗子皆不入眼,年近三十仍形單影只,近日發表一通...
    亦花閱讀 788評論 5 3
  • 今天是端午節,天好陰,斷續下著雨,是在紀念屈原嗎?我一個人在屋里,從昨晚開始到現在,沒有飯吃,沒人說話,就這么過了
    擺好pose很重要閱讀 283評論 0 0
  • 晚上,B妹子和同學打電話,提到了這個年紀最該談論的話題-戀愛與婚姻。 “沒時間啊,而且我還是一個顏控,長得好看的又...
    伍藝邇閱讀 288評論 0 0