《Swift进阶》王巍译——集合类型协议

关联的文章:
Swift进阶(内建集合类型)—一个非科班码农的成长记录

2017.08.09

序列

Sequence 协议是集合类型结构中的基础。一个序列 (sequence) 代表的是一系列具有相同类型的值,你可以对这些值进行迭代。

满足Sequence协议的要求十分简单,你需要做的所有事情就是提供一个返回迭代器(iterator)的makeIterator()方法:

protocol Sequence{
    
    associatedtype Iterator: IteratorProtocol
    func makeIterator() -> Iterator
    
}

迭代器

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

你经常会见到Iterator.Element,实际上这里的Element就是IteratorProtocol中所定义的。

从本质上说,for循环其实是下面这段代码的一种简写形式:

var some = [1, 2, 3, 4]
var iterator = some.makeIterator()
//for循环 是这段代码的简写
while let element = iterator.next() {
    print(element)
}

也可以创建一个无线的,永不枯竭的序列。最简单的情况就是一个不断返回同样值的迭代器了

struct ConstantIterator: IteratorProtocol{
    
    typealias Element = Int
    mutating func next() -> Int? {
        return 1
    }
}

var iter = ConstantIterator()
//while let x = iter.next() {
//    print(x)
//    //这个会死循环
//}

接下来看一个更有意义的例子,FibsIterator迭代器可以产生一个斐波那契序列。

struct FibsIterator:IteratorProtocol{
    
    var state = (0,1)
    //加上mutating修饰 才能对自身的state进行修改
    mutating func next() -> Int?{
        
        let upNum = state.0
        state = (state.1, state.0 + state.1)
        return upNum
        
    }
}

var fibs = FibsIterator()
while let fib = fibs.next() {
    //停止的判断,不然会循环至死
    guard fib < 145 else {
        break
    }
    print(fib)
}

遵守序列协议

struct PrefixIterator: IteratorProtocol{
    
    let 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.startIndex..<offset]
        
    }
}


//记得屏蔽一开始自定义的协议,  不然会报错error: type 'PrefixSequence' does not conform to protocol 'Sequence'
struct PrefixSequence: Sequence{
    
    let string: String
    
    func makeIterator() -> PrefixIterator{
        return PrefixIterator.init(string: string)
    }
    
}

var prefix = PrefixSequence.init(string: "Hello")
for char in prefix {
    print(char)
}

var pre = PrefixIterator.init(string: "World")
while let p = pre.next() {
    print(p)
}

//全部替换成大写
let ma = prefix.map({ $0.uppercased() })
ma

迭代器和值语义

let seq = stride(from: 0, to: 10, by: 1)
var i1 = seq.makeIterator()
i1.next()  //0
i1.next()  //1

var i2 = i1
i2.next()  //2
i2.next()  //3
i1.next()  //2
i1.next()  //3
//i1和i2是分开且独立的了。

//一个不具有值语义的迭代器例子
var i3 = AnyIterator(i1)
var i4 = i3

i3.next()  //4
i4.next()  //5
i3.next()  //6
i4.next()  //7
//共享一个迭代器

基于函数的迭代器和序列
通过一个返回AnyIterator的函数来定义斐波那契迭代器:

func fibsIterator() -> AnyIterator<Int>{
    
    var state = (0, 1)
    return AnyIterator{
        let upNum = state.0
        state = (state.1, state.0 + state.1)
        return upNum
    }
    
}

let fibsSequence = AnySequence.init(fibsIterator())
Array.init(fibsSequence.prefix(10))  //[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
Array.init(fibsSequence.prefix(2))  //[55, 89]

Swift3中引入的sequence函数,这个函数有两种版本。首先sequence(first:next:)将使用第一个参数的值作为序列的首个元素,并使用next参数传入的闭包生成序列的后续元素。下面的例子中,我们生成一个随机数的序列,其中每个元素都要比前一个小,直到到达0为止:

let randomNumbers = sequence(first: 100) { (previous: UInt32) in
    
    let newValue = arc4random_uniform(previous)
    guard newValue > 0 else {
        return nil
    }
    return newValue
}
Array.init(randomNumbers)  //[100, 14, 8, 6, 2]

另一个是sequence(state:next:),因为它可以在两次next闭包被调用之间保存任意的可变状态,所以它更强大一些。我们可以用它来通过以及一个单一的方法调用来构建出斐波那契序列

let fibs2 = sequence(state: (0, 1)) { (state: inout(Int, Int)) -> Int? in
    
    let upNum = state.0
    state = (state.1, state.0 + state.1)
    return upNum
    
}

Array.init(fibs2.prefix(10))  //[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
Array.init(fibs2.prefix(3))  //[0, 1, 1]

看书看得我直打瞌睡哟 =。=,搜索下发现应该是信息转化率不行,果然还是代码功底太差啊!!!

2017.08.19

人生的大起大落太快,实在是太刺激了!

这么久没更新学习状态,确实是太过分了。但是我也不想啊,具体回溯到上星期。上星期四告诉我说要开始做新项目了。星期一开会说月底就要。



你以为代码是复制粘贴就可以有的嘛? 还真是呢。。。 是个屁呀,我是对自己有要求的人,所以还是开始搭建新框架,然后开始做呗。(月底就要肯定功能不会太多,慢慢迭代嘛,加班咯,还能怎么办? 摊手.jpg)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容