IteratorProtocol
声明
protocol IteratorProtocol<Element>
概述
IteratorProtocol
协议与Sequence
协议紧密相连。序列通过创建一个迭代器来提供对其元素的访问,该迭代器跟踪其迭代过程并在它通过序列时一次返回一个元素。
每当您使用带有数组、集合或任何其他集合或序列的 for
- in
循环时,您都在使用该类型的迭代器。 Swift 在内部使用序列或集合的迭代器来启用 for
- in
循环语言结构。
直接使用序列的迭代器可以让您以与使用 for
- in
循环迭代该序列相同的顺序访问相同的元素。例如,您通常可以使用 for
- in
循环来打印数组中的每个元素。
let animals = ["Antelope", "Butterfly", "Camel", "Dolphin"]
for animal in animals {
print(animal)
}
// Prints "Antelope"
// Prints "Butterfly"
// Prints "Camel"
// Prints "Dolphin"
在幕后,Swift 使用 animals
数组的迭代器来循环数组的内容。
var animalIterator = animals.makeIterator()
while let animal = animalIterator.next() {
print(animal)
}
// Prints "Antelope"
// Prints "Butterfly"
// Prints "Camel"
// Prints "Dolphin"
对 animals.makeIterator()
的调用返回数组迭代器的一个实例。接下来,while
循环重复调用迭代器的 next()
方法,绑定每个返回到 animal
的元素,并在 next()
方法返回 nil
时退出。
直接使用迭代器
您很少需要直接使用迭代器,因为 for
- in
循环是在 Swift 中遍历序列的更惯用的方法。然而,一些算法可能需要直接使用迭代器。
一个示例是reduce1(_:)
方法。与标准库中定义的reduce(_:_:)
方法类似,该方法采用初始值和组合闭包,reduce1(_:)
使用序列的第一个元素作为初始值。
这是reduce1(_:)
方法的实现。序列的迭代器直接用于在遍历序列的其余部分之前检索初始值。
extension Sequence {
func reduce1(
_ nextPartialResult: (Element, Element) -> Element
) -> Element?
{
var i = makeIterator()
guard var accumulated = i.next() else {
return nil
}
while let element = i.next() {
accumulated = nextPartialResult(accumulated, element)
}
return accumulated
}
}
reduce1(_:)
方法使某些类型的序列操作更简单。下面以前面介绍的animals
数组为例,说明如何查找序列中最长的字符串:
let longestAnimal = animals.reduce1 { current, element in
if current.count > element.count {
return current
} else {
return element
}
}
print(longestAnimal)
// Prints Optional("Butterfly")
使用多个迭代器
每当您在单个序列上使用多个迭代器(或 for
- in
循环)时,请确保您知道特定序列支持重复迭代,因为您知道它的具体类型或因为序列也被限制为 Collection
协议。
通过对序列的 makeIterator()
方法的单独调用而不是通过复制来获取每个单独的迭代器。复制迭代器是安全的,但通过调用 next()
方法推进迭代器的一个副本可能会使该迭代器的其他副本无效。 for
- in
循环在这方面是安全的。
将IteratorProtocol 一致性添加到您的类型
实现符合IteratorProtocol
的迭代器很简单。声明一个 next()
方法,该方法在相关序列中前进一步并返回当前元素。当序列耗尽时,next()
方法返回 nil
。
例如,考虑一个自定义 Countdown
序列。您可以使用起始整数初始化Countdown
序列,然后将计数迭代到零。 Countdown
结构的定义很简短:它只包含起始计数和Sequence
协议所需的makeIterator()
方法。
struct Countdown: Sequence {
let start: Int
func makeIterator() -> CountdownIterator {
return CountdownIterator(self)
}
}
makeIterator()
方法返回另一个自定义类型,一个名为 CountdownIterator
的迭代器。 CountdownIterator
类型跟踪它正在迭代的 Countdown
序列以及它返回值的次数。
struct CountdownIterator: IteratorProtocol {
let countdown: Countdown
var times = 0
init(_ countdown: Countdown) {
self.countdown = countdown
}
mutating func next() -> Int? {
let nextNumber = countdown.start - times
guard nextNumber > 0
else { return nil }
times += 1
return nextNumber
}
}
每次在 CountdownIterator
实例上调用 next()
方法时,它都会计算新的下一个值,检查它是否已达到零,然后返回数字,如果迭代器完成返回元素,则返回 nil
的序列。
创建和迭代 Countdown
序列使用 CountdownIterator
来处理迭代。
let threeTwoOne = Countdown(start: 3)
for count in threeTwoOne {
print("\(count)...")
}
// Prints "3..."
// Prints "2..."
// Prints "1..."
可用版本
相关用法
- Swift IteratorProtocol next()用法及代码示例
- Swift IteratorSequence prefix(while:)用法及代码示例
- Swift IteratorSequence max(by:)用法及代码示例
- Swift IteratorSequence forEach(_:)用法及代码示例
- Swift IteratorSequence min()用法及代码示例
- Swift IteratorSequence drop(while:)用法及代码示例
- Swift IteratorSequence filter(_:)用法及代码示例
- Swift IteratorSequence joined()用法及代码示例
- Swift IteratorSequence flatMap(_:)用法及代码示例
- Swift IteratorSequence reduce(into:_:)用法及代码示例
- Swift IteratorSequence contains(where:)用法及代码示例
- Swift IteratorSequence dropFirst(_:)用法及代码示例
- Swift IteratorSequence split(maxSplits:omittingEmptySubsequences:whereSeparator:)用法及代码示例
- Swift IteratorSequence joined(separator:)用法及代码示例
- Swift IteratorSequence max()用法及代码示例
- Swift IteratorSequence dropLast(_:)用法及代码示例
- Swift IteratorSequence compactMap(_:)用法及代码示例
- Swift IteratorSequence map(_:)用法及代码示例
- Swift IteratorSequence first(where:)用法及代码示例
- Swift IteratorSequence sorted(by:)用法及代码示例
- Swift IteratorSequence enumerated()用法及代码示例
- Swift IteratorSequence min(by:)用法及代码示例
- Swift IteratorSequence lexicographicallyPrecedes(_:)用法及代码示例
- Swift IteratorSequence用法及代码示例
- Swift IteratorSequence prefix(_:)用法及代码示例
注:本文由纯净天空筛选整理自apple.com大神的英文原创作品 IteratorProtocol。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。