Protocol - IteratorProtocol

2020-12-11  本文已影响0人  sasky2008
public protocol IteratorProtocol {

    /// The type of element traversed by the iterator.
    associatedtype Element

    /// Advances to the next element and returns it, or `nil` if no next element
    /// exists.
    ///
    /// Repeatedly calling this method returns, in order, all the elements of the
    /// underlying sequence. As soon as the sequence has run out of elements, all
    /// subsequent calls return `nil`.
    ///
    /// You must not call this method if any other copy of this iterator has been
    /// advanced with a call to its `next()` method.
    ///
    /// The following example shows how an iterator can be used explicitly to
    /// emulate a `for`-`in` loop. First, retrieve a sequence's iterator, and
    /// then call the iterator's `next()` method until it returns `nil`.
    ///
    ///     let numbers = [2, 3, 5, 7]
    ///     var numbersIterator = numbers.makeIterator()
    ///
    ///     while let num = numbersIterator.next() {
    ///         print(num)
    ///     }
    ///     // Prints "2"
    ///     // Prints "3"
    ///     // Prints "5"
    ///     // Prints "7"
    ///
    /// - Returns: The next element in the underlying sequence, if a next element
    ///   exists; otherwise, `nil`.
    mutating func next() -> Self.Element?
}

提供了遍历的能力, 支持for in. 是数组的基础。
也就是Sequence 和 Collection的基础。

合理运用可以提高很多效率, 比如尾随闭包提供条件进行数据处理。

extension Sequence {

    func condition(_ nextResult: (Element, Element) -> Element) -> Element? {
        // 获取数据流
        var i = makeIterator()
        guard var accumulated = i.next() else {
            return nil
        }
        while let element = i.next() {
            accumulated = nextResult(accumulated, element)
        }
        return accumulated
    }
}

if let max = [1, 2, 4, 3].condition { (value, value1) -> Int in
    return value > value1 ? value : value1
    } {
    print(max)
}

// print 4

比较推荐动手写一下, 下面的代码, 很有趣。

struct CountDown: Sequence {
 
    let start: Int
    func makeIterator() -> CountdownIterator {
        return CountdownIterator(self)
    }
}

struct CountdownIterator: IteratorProtocol {
    let countDown: CountDown
    init(_ countDown: CountDown ) {
        self.countDown = countDown
    }
    var times = 0
    
    mutating func next() -> Int? {
        let nextNumber = countDown.start - times
        guard nextNumber > 0 else {
            return nil
        }
        times += 1
        return nextNumber
    }
}

let fourToOne = CountDown(start: 4)
fourToOne.forEach { print($0) }

// print 
// 4
// 3
// 2
// 1

当然也可以手动调用 .next()

上一篇 下一篇

猜你喜欢

热点阅读