[swift 進階]讀書筆記-集合型別協議 C3P1_序列

liaoWorking在掘金發表於2019-03-01

集合型別協議


3.1序列: sequence

知識點1:滿足sequence協議只需提供一個返回迭代器(iterator):的makeIterator方法。 集合<-Sequence<-Iterator

迭代器:Iterator


裡面只有一個方法next( )

public protocol IteratorProtocol {
	///關聯型別 Element 指定了迭代器產生的值的型別 
	///如 subViews的迭代原生型別就是View 可以不用寫,編譯器根據next()的返回值自動判斷。
	associatedtype Element
	
	///你只需要在每次呼叫的時候返回下一個值,結束時返回nil
	public mutating func next() -> Self.Element?
}
複製程式碼

next( )方法是用 mutating 關鍵字修飾。 幾乎所有的迭代器都要求是可變狀態,這樣才可以管理在序列中的當前位置—-(這句話的意思到現在還沒太理解。大家可以把自己的理解寫上了,thanks~)

下面我們用迭代器寫一個斐波那契數列(0,1,1,2,3,5,8,13…..)。

struct FibsNumIterator:IteratorProtocol {
    var startNum = (0, 1)
    mutating func next() -> Int? {
        let nextNum = startNum.0
        startNum = (startNum.1, startNum.0 + startNum.1)
        return nextNum
    }
}
複製程式碼

這個迭代器不返回nil, 就會產生無窮的陣列。 程式會因為型別溢位而crash。

注:迭代器是單向結構,只能按照增加的方向前進,不能倒退或者重置。

準守序列(sequence)協議


下面我們通過一個列印一個字串所有字首的demo 通過自定義迭代器自定義集合去寫一個屬於你的集合~

第一步: 建立一個迭代器(Iterator)

struct PrefixStrIterator:IteratorProtocol {
    var string: String
    var offset: String.Index
    init(string:String) {
        self.string = string
        offset = string.startIndex
    }
    ///寫協議方法
    mutating func next() -> String? {
        guard offset < string.endIndex else { return nil}
        offset = string.index(after: offset)
        return String(string[string.startIndex..<offset])
    }
}
複製程式碼

第二步: 建立一個使用這個迭代器的序列(sequence)

///step2.建立一個屬於你的集合
struct PrefixSequence: Sequence {
    var string: String
    
    ///協議方法:返回一個迭代器
    func makeIterator() -> PrefixStrIterator {
        return PrefixStrIterator(string: string)
    }
}
複製程式碼

第三步: run~

        ///myfirstSquence 我的第一個集合
        for prefixStr in PrefixSequence(string: "Hi~LiaoWorking!") {
            print(prefixStr)
//            H
//            Hi
//            Hi~
//            Hi~L
//            Hi~Li
//            Hi~Lia
//            Hi~Liao
//            Hi~LiaoW
//            Hi~LiaoWo
//            Hi~LiaoWor
//            Hi~LiaoWork
//            Hi~LiaoWorki
//            Hi~LiaoWorkin
//            Hi~LiaoWorking
//            Hi~LiaoWorking!
        }
複製程式碼

迭代器和值語義


先說說值語義和引用語義,這兩個定義無論在今後的學習還是日常開發細節中會經常遇到~ 敲黑板!

作用物件 特性
值語義 struct,應該還有其他型別。待補充。 賦值時不存在引用,複製了一份過去了
引用語義 class 賦值時存在引用

注:但AnyIterator這個是引用物件。。(協議章中的型別抹消的內容我們再具體說~)

基於函式的迭代器和序列


繼續寫一個Demo: AnyIterator還有一個初始化方法就是直接接受next()函式來當做引數。然後通過引用語義的特性,我們可以不建立新的型別就寫一個斐波那契迭代器

/// 通過引用語義的特性寫斐波那契
func fibsIterator() -> AnyIterator<Any> {
    var startNum = (0, 1)
    return AnyIterator{
        let nextNum = startNum.0
            startNum = (startNum.1 , startNum.0 + startNum.1)
        return nextNum
    }
}
複製程式碼

這個是高階知識點,的確沒有第二章的生動。瞭解一下也挺好啊~~

無限序列


序列可以是無限的,而集合是有限的。

不穩定序列


Sequence文件明確指出序列並不保證能被多次遍歷。
原因是Sequence協議並不關心裡面的序列元素會不會銷燬。

知識點1:這就是為什麼在集合型別中.first 在序列中並不存在。

序列sequence和迭代器Iterator的關係

迭代器Iterator可以看成即將返回的元素組成的不穩定序列sequence

子序列


Sequence還有一個關聯型別 SubSequence

在返回原序列Sequence的切片slice操作中,SubSequence會被當做返回值的子類。

SubSequence 有一些常用方法

prefix 
suffix
dropFirst
dropLast
split
複製程式碼

在專案中其實經常會遇到SubSequence,如string的SubSequence等等。。(哈哈才一個,這個不能叫“經常”。其實是會經常遇到SubSequence。不過一時之間想不起來了?)

文章原始檔地址

相關文章