小斑SwiftiOS学习开发

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

2017-08-09  本文已影响353人  Bart_Simpson

关联的文章:
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)

上一篇下一篇

猜你喜欢

热点阅读