Sequence & Iterator & 高阶函数

245 阅读2分钟
let nums = [1, 2, 3, 4]

for num in nums {
    print(num)
}

Sequence & Iterator

查看以上代码在sil中是如何实现的 截屏2021-03-30 上午10.20.51.png

截屏2021-03-30 上午10.29.07.png对于for in来说就是先拿到集合,再拿到Iterator迭代器,再通过迭代器中的next不断的访问当前的元素。 查看swift源码 截屏2021-03-30 上午11.28.45.png仿写

截屏2021-03-30 下午2.36.15.png本质上就是先生成Sequence,再去生成Iterator,接下来调用Iterator的next方法来生产元素

Collection

array和Dictionary针对Sequence又做了一遍继承,也就是Collection

截屏2021-03-30 下午2.57.47.png

环形缓冲区

截屏2021-03-30 下午3.24.08.png 仿写环形缓冲区 截屏2021-03-30 下午3.50.55.png

  • %运算是开销很大的,怎样能用其他运算来代替%运算
  • 怎么来判断环形缓冲区已经满了
  • 如果删除一个元素,删除的逻辑是什么

问题1 截屏2021-03-30 下午5.27.34.png 修改上看的代码

struct RingBuffer<Element> {
    //存数据容器
    var _buffer: ContiguousArray<Element?>
    //头部位
    var headIndex: Int = 0
    //尾部位
    var tailIndex: Int = 0
    //最后一个元素的下标
    var mask: Int{
        return self._buffer.count - 1
    }

    //初始化
    init(_ count: Int) {
        //算出距离元素个数的最小的2^n次方
        let tmp = count.nextPowerOf2()
        //初始化容器
       _buffer = ContiguousArray<Element?>(repeating: nil, count: tmp)
    }

    //求tailIndex
    mutating func advanceTailIndex(by: Int) {
        self.tailIndex = (self.tailIndex + by) & self.mask
    }
    //求headIndex
    mutating func advanceHeadIndex(by: Int){
        self.headIndex = (self.headIndex + by) & self.mask
    }

    func indexAdvanced(index: Int, by: Int) -> Int{
        return (index + by) & self.mask
    }

    //添加元素
    mutating func append(_ value : Element) {
        //向容器中添加元素
        self._buffer[self.tailIndex] = value
        //求tailIndex
        self.advanceTailIndex(by: 1)

        if self.headIndex == self.tailIndex {
            fatalError("out of bounds")
        }
    }

    mutating func pop() -> Element? {
        //读取元素
        let result = _buffer[self.headIndex]
        //求headIndex
        self.advanceHeadIndex(by: 1)
        return result
    }
}

//官方给出的能求出与给定数最小的2^n的值
extension FixedWidthInteger {
    @inlinable
    func nextPowerOf2() -> Self {
        guard self != 0 else {
            return 1
        }
        return 1 << (Self.bitWidth - (self - 1).leadingZeroBitCount)
    }
}

//遵守Collection协议实现最基本的方法
extension RingBuffer: Collection {

    func index(after i: Int) -> Int {
            return (i + 1) & self.mask
        }
    //开始位置
    var startIndex: Int {
        return self.headIndex
    }

    //结束位置
    var endIndex: Int {
        return self.tailIndex
    }

    subscript(position: Int) -> Element {
        get {
            return self._buffer[position]!
        }
        set {
            self._buffer[position] = newValue
        }
    }
}

func test() {
    var buf = RingBuffer<Int>.init(9)
    for i in 1...10 {
        buf.append(i)
    }
    
    for element in buf {
        print(element)
    }
}

test()

输出
1
2
3
4
5
6
7
8
9
10

⚠️注意

截屏2021-03-31 上午10.54.31.pnginit填写如果小于遍历的个数会出错

在上面的基础上以字面量的方式来遍历数组 截屏2021-03-31 下午1.21.07.png 删除

截屏2021-03-31 下午1.57.32.png

高阶函数

  • 接受函数或者闭包作为参数
  • 返回值是一个函数或者闭包

截屏2021-03-31 下午2.29.32.png 查看map源码 截屏2021-03-31 下午2.45.34.png

flatMap

Map: return [T]类型的数组

flatMap: return [Element]当前元素的数组

截屏2021-03-31 下午2.55.41.png flatMap和Map的区别还有就是压平

截屏2021-03-31 下午3.00.25.png flatMap返回的是元素的集合

截屏2021-03-31 下午3.08.34.png根据上图可以看出当生命一个可选的number,再把整形转成string再转回来时调用restult会出现需要解包两次

截屏2021-03-31 下午3.12.07.png当换成flatMap时只需要解包一次即可