Protocol

IteratorProtocol

A type that supplies the values of a sequence one at a time. あるシーケンスに属する値を一度に1つ提供する型。

Declaration 宣言

protocol IteratorProtocol

Overview 概要

The IteratorProtocol protocol is tightly linked with the Sequence protocol. Sequences provide access to their elements by creating an iterator, which keeps track of its iteration process and returns one element at a time as it advances through the sequence. IteratorProtocolプロトコルは、Sequenceプロトコルときつく結び付けられています。さまざまなシーケンスは、あるイテレータを作成することによってそれらの要素に対するアクセスを提供します、それはそれの反復処理を追跡し続けてそれがそのシーケンスを始めから終わりへと前進するごとに一度に1つ要素を返します。

Whenever you use a for-in loop with an array, set, or any other collection or sequence, you’re using that type’s iterator. Swift uses a sequence’s or collection’s iterator internally to enable the for-in loop language construct. あなたがfor-inループを配列、集合、または何らかの他のコレクションやシーケンスとともに使うときはいつでも、あなたはこの型のもつイテレータを使っています。Swiftは、あるシーケンスのもつまたはコレクションのもつイテレータを内部的に使うことで、for-inループ言語構成体を可能にしています。

Using a sequence’s iterator directly gives you access to the same elements in the same order as iterating over that sequence using a for-in loop. For example, you might typically use a for-in loop to print each of the elements in an array. あるシーケンスのもつイテレータを直に使うことは、あなたにfor-inループを使ってそのシーケンスに反復するのと同じ要素に同じ順序でアクセスすることを与えます。例えば、あなたは概してfor-inループを使って、ある配列の中の各要素を出力するかもしれません。


let animals = ["Antelope", "Butterfly", "Camel", "Dolphin"]
for animal in animals {
    print(animal)
}
// Prints "Antelope"
// Prints "Butterfly"
// Prints "Camel"
// Prints "Dolphin"

Behind the scenes, Swift uses the animals array’s iterator to loop over the contents of the array. 舞台裏で、Swiftはanimals配列のもつイテレータを使って、その配列の要素のすべてにわたって繰り返します。


var animalIterator = animals.makeIterator()
while let animal = animalIterator.next() {
    print(animal)
}
// Prints "Antelope"
// Prints "Butterfly"
// Prints "Camel"
// Prints "Dolphin"

The call to animals.makeIterator() returns an instance of the array’s iterator. Next, the while loop calls the iterator’s next() method repeatedly, binding each element that is returned to animal and exiting when the next() method returns nil. animals.makeIterator()への呼び出しは、配列のもつイテレータの1つのインスタンスを返します。次に、whileループは、そのイテレータのもつnext()メソッドを繰り返し呼び出して、返される各要素をanimalに束縛して、そしてnext()メソッドがnilを返すとき退出します。

Using Iterators Directly イテレータを直に使う

You rarely need to use iterators directly, because a for-in loop is the more idiomatic approach to traversing a sequence in Swift. Some algorithms, however, may call for direct iterator use. あなたは滅多にイテレータを直に使う必要はありません、なぜならfor-inループはSwiftにおいてシーケンスを辿っていくずっと慣用語法にかなった取り組みだからです。幾つかのアルゴリズムは、しかしながら、直にイテレータを使うために呼び出すかもしれません。

One example is the reduce1(_:) method. Similar to the reduce(_:_:) method defined in the standard library, which takes an initial value and a combining closure, reduce1(_:) uses the first element of the sequence as the initial value. 1つの例はreduce1(_:)メソッドです。初期値と結合クロージャをとる、標準ライブラリ定義のreduce(_:_:)メソッドとよく似て、 reduce1(_:)はシーケンスの最初の要素を初期値として使います。

Here’s an implementation of the reduce1(_:) method. The sequence’s iterator is used directly to retrieve the initial value before looping over the rest of the sequence. ここに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
    }
}

The reduce1(_:) method makes certain kinds of sequence operations simpler. Here’s how to find the longest string in a sequence, using the animals array introduced earlier as an example: reduce1(_:)メソッドは、特定の種類のシーケンス演算をより簡単にします。ここに最も長い文字列をあるシーケンスの中で見つける方法があります、前に導入されたanimals配列を例として使っています:


let longestAnimal = animals.reduce1 { current, element in
    if current.count > element.count {
        return current
    } else {
        return element
    }
}
print(longestAnimal)
// Prints Optional("Butterfly")

Using Multiple Iterators 複数のイテレータを使う

Whenever you use multiple iterators (or for-in loops) over a single sequence, be sure you know that the specific sequence supports repeated iteration, either because you know its concrete type or because the sequence is also constrained to the Collection protocol. あなたが複数のイテレータ(またはfor-inループ)をある単一のシーケンスに対して使うときはいつでも、その特定のシーケンスが繰り返される反復をサポートすると確実にあなたが知っているようにしてください、あなたがそれの具体的な型を知っているからかもしくはそのシーケンスもまたCollectionプロトコルに制約されるからかのどちらかで。

Obtain each separate iterator from separate calls to the sequence’s makeIterator() method rather than by copying. Copying an iterator is safe, but advancing one copy of an iterator by calling its next() method may invalidate other copies of that iterator. for-in loops are safe in this regard. そのシーケンスのもつmakeIterator()メソッドへの独立した呼び出しから独立したイテレータを取得してください、コピーによってではなく。あるイテレータをコピーすることは安全です、しかしあるインスタンスの1つのコピーをそれのメソッドnext()メソッドを呼び出すことによって前に進めることは、そのイテレータの他のコピーを無価値にするでしょう。for-inループはこの点に関して安全です。

Adding IteratorProtocol Conformance to Your Type IteratorProtocol準拠をあなたの型に加える

Implementing an iterator that conforms to IteratorProtocol is simple. Declare a next() method that advances one step in the related sequence and returns the current element. When the sequence has been exhausted, the next() method returns nil. IteratorProtocolに準拠するイテレータを実装するのは簡単です。next()メソッドを宣言してください、それは関連シーケンスにおいて一歩前へ進みます、そして現在の要素を返します。そのシーケンスが使い尽くされたならば、next()メソッドはnilを返します。

For example, consider a custom Countdown sequence. You can initialize the Countdown sequence with a starting integer and then iterate over the count down to zero. The Countdown structure’s definition is short: It contains only the starting count and the makeIterator() method required by the Sequence protocol. 例えば、あるあつらえのCountdownシーケンスを考えてください。あなたは、Countdownシーケンスをある開始点整数で初期化してそれからカウントダウンをゼロまでずっと反復することができます。Countdown構造体の定義は短いです:それはただ数え始めとSequenceプロトコルによって要求されるmakeIterator()メソッドだけを含みます。


struct Countdown: Sequence {
    let start: Int


    func makeIterator() -> CountdownIterator {
        return CountdownIterator(self)
    }
}

The makeIterator() method returns another custom type, an iterator named CountdownIterator. The CountdownIterator type keeps track of both the Countdown sequence that it’s iterating and the number of times it has returned a value. 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
    }
}

Each time the next() method is called on a CountdownIterator instance, it calculates the new next value, checks to see whether it has reached zero, and then returns either the number, or nil if the iterator is finished returning elements of the sequence. next()メソッドがCountdownIteratorインスタンス上で呼ばれるたびに、それは新しい次の値を計算し、それがゼロに届いたか見るために調べ、そしてそれからその数、またはそのイテレータがシーケンスの要素を返すことを完了するならばnilのどちらかを返します。

Creating and iterating over a Countdown sequence uses a CountdownIterator to handle the iteration. Countdownシーケンス全体にわたっての作成や反復は、その反復を取り扱うCountdownIteratorを使用します。


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

Topics 話題

Associated Types さまざまな関連型

Instance Methods インスタンスメソッド

Relationships 関係

Conforming Types これらの型が準拠