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。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。