美文网首页
Swift 集合类新协议 Sequence

Swift 集合类新协议 Sequence

作者: 你duck不必呀 | 来源:发表于2021-11-04 10:51 被阅读0次

    序列

    序列代表一系列类型相同的元素,你可以对这些元素进行迭代

    Sequence协议

    Sequence协议是集合类型的基础,Swift中Sequence协议为序列提供了迭代的能力。Sequence 协议只要求实现makeIterator()方法,该方法返回一个迭代器Iterator;

    public protocol Sequence {
      // 元素类型
      associatedtype Element 
      // 迭代器类型 == 元素类型
      associatedtype Iterator: IteratorProtocol where Iterator.Element == Element
      //迭代器
      __consuming func makeIterator() -> Iterator
      //...
    }
    

    迭代器

    序列通过创建一个迭代器来提供对元素的访问。迭代器每次产生一个序列的值,并且当遍历序列时对遍历状态进行管理。在 IteratorProtocol 协议中唯一的一个方法是 next(),这个方法需要在每次被调用时返回序列中的下一个值。当序列被耗尽时,next() 返回 nil

    public protocol IteratorProtocol {
      /// The type of element traversed by the iterator.
      associatedtype Element
      mutating func next() -> Element?
    }
    

    for循环的背后是编译器创建了一个迭代器,然后不断的调用next(),直到返回nil

    // 猜测编译器实现 for
    var iter = CustomIterator()
    while let x = iter.next(){
            //...
    }
    

    看一个例子

    自定义迭代器类型,遵守IteratorProtocol协议,不需要指明Element类型,编译器会从next的返回类新推断出Element的类型

    自定义序列,遵守Sequence协议,同样不需要指明Element类型,编译器会从makeIterator的类型中推断出Element类型。

    最后通过for-in 就能不断打印结果了

    struct customProtocol:IteratorProtocol{
            //Element 可以省略,编译器会从next的返回类新推断出Element的类型
            //typealias Element = Int
        func next() -> Int? {
            return 1
        }
    }
    //...
    struct customSequence: Sequence{
            //同样,编译器会从makeIterator的类型中推断出Element类型,不需要再次指明
        func makeIterator() -> some IteratorProtocol {
            customProtocol()
        }
    }
    //...
    var customPrint = customSequence()
    for i in customPrint{
        print(i) // 由于next返回1,所以这里会无限打印 
    }
    

    扩展的Sequence

    上面的例子,除了能正常通过for - in遍历,还能进行其他操作(例如:map)这是因为系统对Sequence协议做了扩展extension,扩展后的协议支持以下操作:

    • map(:) 和flatMap(:) 对序列中的每个值转换 生成新的序列

    • filter(:) 根据条件过滤元素

    • first:满足给定条件的最值

    • forEach:类似OC中的block枚举

    • drop 、dropFirst、dropLast 满足相反条件的切片操作

    • prefix、suffix 满足条件的切片操作

    迭代器的值语义

    在对一个序列进行for循环遍历的时候,底层默认实现是依赖迭代器,迭代器是一个struct类型,swift中的struct具有值语义;如果复制一份,两个迭代器分别在自己的范围工作,这是期望的结果

    // strideToIterator是一个简单的迭代器
    let seq = stride(from: 1, to: 5, by: 1)
    var itr1 = seq.makeIterator()
    var iter2 = iter
    // iter和iter2调用结果互不影响
    //iter 
    iter.next() // Optional(1)
    iter.next() // Optional(2)
    //iter2 
    iter2.next() // Optional(1)
    iter2.next() // Optional(2)
    

    枚举器

    遵守Sequence协议的的类型,可以通过enumerated()将一个序列转换成另一个带有递增数字的新序列。

    var customPrint = customSequence()
    customPrint.enumerated()
    //...
    for (i,value) in customPrint.enumerated(){
        print(i,value)
    }
    

    子序列

    subSequence 是Sequence的另一个关联类型,通过切片操作(split,prefix,suffix,drop等)会返回subSequence类型,自定义序列如果没有明确指明类新,系统会推断位AnySequence<Iterator.Element>类型(例如:字符串String,子类型subString)

    子序列和原序列的类型一致,由于系统优化,在没有对子序列修改之前会复用原序列的内存空间

    相关文章

      网友评论

          本文标题:Swift 集合类新协议 Sequence

          本文链接:https://www.haomeiwen.com/subject/igohzltx.html