文書   >   Swift 標準ライブラリ >     Collections   >   Sequence and Collection   >   IteratorProtocol


プロトコル


IteratorProtocol


一度に1つずつシーケンスの値を供給する型。




概観


IteratorProtocol プロトコルは、Sequence プロトコルと緊密にリンクされています。シーケンスは、繰り返し因子を作成することによって要素へのアクセスを提供し、繰り返し因子は、その繰り返し処理を追跡し、シーケンスを進めるにつれて一度に 1 つの要素を返します。


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 のシーケンスを横断するための、より慣用的なアプローチであるため、繰り返し因子を直接使用する必要はほとんどありません。ただし、一部のアルゴリズムでは、繰り返し因子を直接使用する必要があります。


1 つの例は 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 "Butterfly"


複数の繰り返し因子の使用


単一のシーケンスに対して複数の繰り返し因子(または for-in ループ) を使用する場合はいつでも、その具体的な型がわかっているか、シーケンスが Collection プロトコルにも制約されているため、特定のシーケンスが繰り返しをサポートしていることを確認してください。


コピーするのではなく、シーケンスの makeIterator() メソッドを別々に呼び出して、それぞれ別の繰り返し因子を取得して下さい。繰り返し因子をコピーすることは安全ですが、その next() メソッドを呼び出すことによって繰り返し因子のコピーを 1 つ進めると、その繰り返し因子の他のコピーが無効になることがあります。for-in ループはこの点で安全です。


型に IteratorProtocol の準拠性を追加


IteratorProtocol に準拠する繰り返し因子を実装するのは簡単です。関連するシーケンスで 1 つのステップを進める 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
    }
}


next() メソッドが CountdownIterator インスタンスで呼び出されるたびに、新しい次の値が計算され、ゼロに達したかどうかがチェックされ、数値が返されるか、繰り返し因子がシーケンスの要素を返し終わった場合は nil を返すかのいずれかです。


Countdown シーケンスの作成と反復では、CountdownIterator を使用して繰り返しを処理します。


let threeTwoOne = Countdown(start: 3)
for count in threeTwoOne {
    print("\(count)...")
}
// Prints "3..."
// Prints "2..."
// Prints "1..."


トピックス





関連した型





インスタンスメソッド


関連





以下により採用






目次
Xcode の新機能

  • 言語:Swift
  • SDK
  • macOS 8.0+
  • フレームワーク
  • Swift 標準ライブラリ
  • 概観
  • トピックス
  • 関連












  • トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)












    トップへ(Swift 標準ライブラリ)