let nums = [1, 2, 3, 4]
for num in nums {
print(num)
}
Sequence & Iterator
查看以上代码在sil中是如何实现的
对于for in来说就是先拿到集合,再拿到Iterator迭代器,再通过迭代器中的next不断的访问当前的元素。
查看swift源码
仿写
本质上就是先生成Sequence,再去生成Iterator,接下来调用Iterator的next方法来生产元素
Collection
array和Dictionary针对Sequence又做了一遍继承,也就是Collection
环形缓冲区
仿写环形缓冲区
- %运算是开销很大的,怎样能用其他运算来代替%运算
- 怎么来判断环形缓冲区已经满了
- 如果删除一个元素,删除的逻辑是什么
问题1
修改上看的代码
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
⚠️注意
init填写如果小于遍历的个数会出错
在上面的基础上以字面量的方式来遍历数组
删除
高阶函数
- 接受函数或者闭包作为参数
- 返回值是一个函数或者闭包
查看map源码
flatMap
Map: return [T]类型的数组
flatMap: return [Element]当前元素的数组
flatMap和Map的区别还有就是压平
flatMap返回的是元素的集合
根据上图可以看出当生命一个可选的number,再把整形转成string再转回来时调用restult会出现需要解包两次
当换成flatMap时只需要解包一次即可