イテレータ

ウィキペディアから、無料の百科事典
ナビゲーションにジャンプ 検索にジャンプ

コンピュータープログラミングではイテレーターは、プログラマーがコンテナー、特にリストをトラバースできるようにするオブジェクトです。[1] [2] [3]さまざまなタイプのイテレータが、コンテナインターフェイスを介して提供されることがよくあります。特定のイテレーターのインターフェースとセマンティクスは固定されていますが、イテレーターはコンテナー実装の基礎となる構造の観点から実装されることが多く、イテレーターの操作的セマンティクスを有効にするためにコンテナーに緊密に結合されることがよくあります。イテレータはトラバーサルを実行し、コンテナ内のデータ要素へのアクセスも提供しますが、それ自体は実行しません反復(つまり、その概念または用語の些細な使用で取られたいくつかの重要な自由がないわけではありません)[要出典]

イテレータは、動作がデータベースカーソルに似ていますイテレータは1974年にCLUプログラミング言語にさかのぼります。

説明

内部イテレータ

内部イテレータは、 mapreduceなどの高階関数(多くの場合無名関数を使用)であり、コンテナ全体のトラバーサルを実装し、指定された関数をすべての要素に順番に適用します。

外部イテレータとイテレータパターン

外部イテレータは、オブジェクトコレクション内の特定の要素を参照する(要素アクセスと呼ばれる)ことと、次の要素を指すようにそれ自体を変更する(要素トラバーサルと呼ばれる)という2つの主要な操作を持つポインタの一種と考えることができます。[4]イテレータを作成して最初の要素を指すようにする方法と、イテレータがコンテナ内のすべての要素を使い果たした時期を判断する方法も必要です。言語と使用目的に応じて、イテレータは追加の操作を提供したり、異なる動作を示したりする場合もあります。

イテレータの主な目的は、ユーザーをコンテナの内部構造から分離しながら、ユーザーがコンテナのすべての要素を処理できるようにすることです。[2]これにより、コンテナは要素を任意の方法で格納できると同時に、ユーザーはそれを単純なシーケンスまたはリストであるかのように扱うことができます。イテレータクラスは通常、対応するコンテナクラスと緊密に連携して設計されます。通常、コンテナはイテレータを作成するためのメソッドを提供します。

ループカウンタは、ループイテレータと呼ばれることもありますただし、ループカウンターはトラバーサル機能のみを提供し、要素アクセス機能は提供しません。

ジェネレーター

イテレータを実装する1つの方法は、ジェネレータとして知られる制限された形式のコルーチンを使用することです。サブルーチンとは対照的に、ジェネレータコルーチンは、1回だけ返すのではなく、呼び出し元に複数回値を返すことができます。ほとんどのイテレータはジェネレータとして自然に表現できますが、ジェネレータは呼び出し間でローカル状態を保持するため、ツリートラバーサーなどの複雑でステートフルなイテレータに特に適しています「ジェネレーター」と「イテレーター」という用語の使用には微妙な違いと違いがあり、作成者と言語によって異なります。[5] Pythonでは、ジェネレーターはイテレーターコンストラクターです:イテレータを返す関数。Pythonのステートメントを使用してフィボナッチ数のイテレータを返すPythonジェネレータの例は次のyieldとおりです。

def  fibonacci limit 
    a  b  =  0、1 for _ in range limit yield a a  b = b a + b
       
         
              

 フィボナッチ100 )数値 の場合 #ジェネレーターはイテレーターの出力を作成します数値 
    

暗黙のイテレータ

C#C ++(後のバージョン)、Delphi(後のバージョン)、GoJava(後のバージョン)、LuaPerlPythonRubyなどの一部のオブジェクト指向言語は、コンテナオブジェクトの要素を反復する本質的な方法を提供します。明示的なイテレータオブジェクトの導入。実際のイテレータオブジェクトは実際に存在する可能性がありますが、存在する場合は、言語のソースコード内に公開されません。[4] [6]

暗黙のイテレータは、次のPythonの例のように 、「 foreach 」ステートメント(または同等のもの)によって表されることがよくあります。

 iterable の場合 print value 
    

Pythonでは、イテレータはイテレータに変換できるオブジェクトであり、イテレータはforループ中に繰り返されます。これは暗黙的に行われます。

または、次のRubyの例のように、コレクションオブジェクト自体によって作成される場合もあります。

反復可能それぞれ が行う | | 
  値を 終了します

この反復スタイルは、コードが反復可能オブジェクト(反復のすべての側面を制御する)のコンテキスト内で完全に実行され、プログラマーが各ステップで実行する操作のみを提供するため(無名関数を使用)、「内部反復」と呼ばれることもあります。

リスト内包表記または同様の構造をサポートする言語は、Pythonの場合のように、結果リストの構築中に暗黙のイテレータを使用する場合もあります。

名前 =  [人の場合名簿に載っている人の名前 男性]     

暗黙の隠された性質が部分的である場合があります。C ++言語には、暗黙の反復用の関数テンプレートがいくつかありますfor_each()これらの関数は、初期入力として明示的なイテレータオブジェクトを必要としますが、後続の反復ではイテレータオブジェクトがユーザーに公開されません。

ストリーム

イテレータは、入力ストリームの便利な抽象化です。イテレータは、潜在的に無限のイテレータ(ただし、必ずしもインデックス可能ではない)オブジェクトを提供します。PerlやPythonなどのいくつかの言語は、イテレータとしてストリームを実装します。Pythonでは、イテレータはデータのストリームを表すオブジェクトです。[7]ストリームの代替実装には、 AWKsedなどのデータ駆動型言語が含まれます。

索引付けとは対照的

手続き型言語では、添え字演算子とループカウンターを使用して、配列などのシーケンス内のすべての要素をループするのが一般的です。一部のオブジェクト指向コンテナーでも索引付けを使用できますが、イテレーターを使用するといくつかの利点があります。[8]

  • カウントループは、すべてのデータ構造、特にリストツリーなどのランダムアクセスがないか遅いデータ構造には適していません
  • イテレータは、あらゆる種類のデータ構造を反復処理するための一貫した方法を提供できるため、コードをより読みやすく、再利用可能にし、データ構造の変更に対する感度を低くすることができます。
  • イテレータは、要素をスキップできないようにしたり、以前にアクセスした要素に2回アクセスできないようにするなど、アクセスに追加の制限を適用できます。
  • イテレータを使用すると、イテレータを無効にすることなく、コンテナオブジェクトを変更できます。たとえば、イテレータが最初の要素を超えて進むと、コンテナの先頭に追加の要素を挿入して、予測可能な結果を​​得ることができる場合があります。インデックス付けでは、インデックス番号を変更する必要があるため、これには問題があります。

オブジェクトと操作の効果との相互関係が明らかでない可能性がある現代のオブジェクト指向プログラミングでは、要素を反復処理しながらコンテナーを変更する機能が必要になりました。イテレータを使用することにより、これらの種類の結果から分離されます。ただし、効率上の理由から、イテレータの実装はコンテナに緊密にバインドされているため、それ自体を無効にすることなく、基になるコンテナの変更を排除することが多いため、このアサーションは一粒の塩で行う必要があります。

メモリ内のデータを移動する可能性のあるコンテナの場合、イテレータを無効にしない唯一の方法は、コンテナの場合、現在有効なすべてのイテレータを追跡し、その場で更新することです。ある時点でのイテレータの数は、タイされたコンテナのサイズと比較して任意に多くなる可能性があるため、それらをすべて更新すると、コンテナの操作の複雑さの保証が大幅に損なわれます。

コンテナーサイズに対してバインドされた更新の数を維持する別の方法は、一種のハンドルメカニズムを使用することです。これは、コンテナーで更新する必要があるコンテナーの要素への間接ポインターのコレクションであり、イテレーターがポイントするようにします。これらのハンドルは、データ要素に直接ではなく。ただし、このアプローチは、実際のデータ要素にアクセスするために後続のダブルポインターを実行する必要があるため、イテレーターのパフォーマンスに悪影響を及ぼします。イテレータを使用する多くのアルゴリズムは、advanceメソッドよりも頻繁にイテレータのデータアクセス操作を呼び出すため、これは通常は望ましくありません。したがって、非常に効率的なデータアクセスを備えたイテレータを用意することが特に重要です。

全体として、これは常にセキュリティ(イテレータは常に有効なままです)と効率の間のトレードオフです。ほとんどの場合、追加されたセキュリティは、それを支払うための効率的な価格の価値がありません。イテレータの安定性が必要な場合は、代替コンテナ(たとえば、ベクトルの代わりに単一リンクリスト)を使用する方が適切です(グローバルに効率的です)。

イテレータの分類

イテレータカテゴリ

イテレータは、その機能に応じて分類できます。イテレータカテゴリの(網羅的ではない)リストは次のとおりです。[9] [10]

カテゴリー 言語
双方向イテレータ C ++
フォワードイテレータ C ++
入力イテレータ C ++
出力イテレータ C ++
ランダムアクセスイテレータ C ++
簡単なイテレータ C ++(古いSTL[11]

イテレータタイプ

さまざまな言語またはこれらの言語で使用されるライブラリは、イテレータタイプを定義します。それらのいくつかは[12]です

タイプ 言語
配列イテレータ PHP、R [13]
キャッシングイテレータ PHP
一定のイテレータ C ++[14] PHP
ディレクトリイテレータ PHP、Python
フィルターイテレーター PHP、R
イテレータを制限する PHP
リストイテレータ Java[6] R
再帰的配列イテレータ PHP
XMLイテレータ PHP

さまざまなプログラミング言語で

C#およびその他の.NET言語

.NET Frameworkのイテレーターは「列挙子」と呼ばれ、インターフェイスによって表されIEnumeratorます。次の要素に進み、コレクションの最後に到達したかどうかを示すメソッドをIEnumerator提供します。MoveNext()現在ポイントされている要素の値を取得するためのCurrentプロパティ。オプションのReset()方法で、列挙子を元の位置に巻き戻します。列挙子は最初に最初の要素の前にある特別な値を指しているため、MoveNext()反復を開始するにはtoを呼び出す必要があります。

列挙子は通常、インターフェイスGetEnumerator()を実装するオブジェクトのメソッドを呼び出すことによって取得されIEnumerableます。コンテナクラスは通常、このインターフェイスを実装します。ただし、C#のforeachステートメントは、実装されていない場合でも、そのようなメソッドを提供する任意のオブジェクトを操作できますダックタイピング)。両方のインターフェースは、 .NET2.0で汎用バージョンに拡張されましたIEnumerable

以下に、C#2.0でのイテレーターの簡単な使用法を示します。

//明示的なバージョン
IEnumerator < MyType >  iter  =  list GetEnumerator (); 
while  iter。MoveNext Console WriteLine iter。current ; _
    

//暗黙のバージョン
foreach  リスト内のMyType  Console WriteLine ); 
    

C#2.0はジェネレーターIEnumeratorもサポートします:returning (またはIEnumerableとして宣言されているメソッドですがyield return、オブジェクトインスタンスを返す代わりに ""ステートメントを使用して要素のシーケンスを生成し、コンパイラーによって適切なインターフェイスを実装する新しいクラスに変換されます。

C++

C ++言語は、標準ライブラリのイテレータを幅広く使用しており、許可される操作のレパートリーが異なるイテレータのいくつかのカテゴリを記述しています。これらには、可能性が高い順に、順方向反復子双方向反復子、およびランダムアクセス反復子が含まれます。すべての標準コンテナテンプレートタイプは、これらのカテゴリのいずれかのイテレータを提供します。イテレータは、配列の要素へのポインタを一般化し(実際にはイテレータとして使用できます)、それらの構文は、C ポインタ演算*の構文に似ているように設計されています->演算子は、イテレーターが指す要素を参照するために使用され、ポインター算術演算子++は、コンテナーのトラバーサルでイテレーターを変更するために使用されます。

イテレータを使用したトラバーサルには、通常、1つの可変イテレータと、トラバースする範囲を区切るのに役立つ2つの固定イテレータが含まれます。++下限を上限に変換するために必要なオペレーターのアプリケーションの数に関する制限イテレーター間の距離は、指定された範囲内のアイテムの数に等しくなります。関連する個別のイテレータ値の数は、それより1つ多くなります。慣例により、下限イテレータは範囲内の最初の要素を「指します」が、上限反復子は範囲内のどの要素も指しませんが、範囲の終わりを少し超えたところを指します。コンテナ全体をトラバースする場合、このbegin()メソッドは下限を提供し、end()上限。後者はコンテナの要素をまったく参照しませんが、比較できる有効なイテレータ値です。

次の例は、イテレータの一般的な使用法を示しています。

std :: vector < int > items ; 
アイテムpush_back 5 ); //整数値「5」をベクター「items」に追加します。アイテムpush_back 2 ); //整数値「2」をベクター「items」に追加します。アイテムpush_back 9 ); //整数値「9」をベクター「items」に追加します。 
 
 

for auto it = items .begin (); it != items .end (); ++ it { // 'items'を反復処理しますstd :: cout << * it ; //そして現在のインデックスの'items'の値を出力します。}          
     

// C ++ 11では、イテレータを使用せずに同じことができます:
for auto x items {     
  std :: cout << x ; //'items'の各要素'x'の値を出力します。}   


//両方のforループは「529」を出力します。

イテレータタイプは、一緒に使用されるコンテナタイプとは別のものですが、2つは一緒に使用されることがよくあります。イテレータのカテゴリ(およびそのために定義された操作)は通常、コンテナのタイプによって異なります。たとえば、配列またはベクトルはランダムアクセスイテレータを提供しますが、セット(実装としてリンク構造を使用)は双方向イテレータのみを提供します。1つの同じコンテナタイプに複数のイテレータタイプを関連付けることができます。たとえば、std::vector<T>コンテナタイプでは、(タイプの*<T>)要素への(生の)ポインタ、または特殊なタイプの値のいずれかを使用してトラバーサルが可能です。std::vector<T>::iterator、さらに別のタイプが「逆イテレータ」に提供されます。その操作は、通常の(順)トラバーサルを実行するアルゴリズムが、逆イテレータで呼び出されたときに実際に逆順でトラバーサルを実行するように定義されます。ほとんどのコンテナは別のconst_iteratorタイプも提供しており、ポイントされた値の変更を可能にする操作は意図的に定義されていません。

コンテナオブジェクトまたはその要素の範囲の単純なトラバース(aconst_iteratorが使用されていない限り、これらの要素の変更を含む)は、イテレータのみを使用して実行できます。ただし、コンテナタイプは、コンテナ自体の構造を変更するようinsertなメソッドを提供する場合もあります。eraseこれらはコンテナクラスのメソッドですが、さらに、目的の操作を指定するために1つ以上のイテレータ値が必要です。複数のイテレータが同じコンテナを同時に指すことは可能ですが、構造を変更する操作により、特定のイテレータ値が無効になる場合があります(標準では、それぞれの場合にそうなるかどうかが指定されています)。無効化されたイテレータの使用は、未定義の動作につながるエラーであり、そのようなエラーはランタイムシステムによって通知される必要はありません。

std::for_each()暗黙の反復は、、、などの 標準関数テンプレートを使用することにより、C++でも部分的にサポートされていstd::copy() ます std::accumulate()

使用する場合は、反復が発生する範囲を定義する既存のイテレータ(通常はbeginおよび)で初期化する必要があります。endただし、反復が進むにつれて、明示的なイテレータオブジェクトはその後公開されません。この例は、の使用法を示していますfor_each

ContainerType < ItemType > c ; //ItemType要素の標準コンテナタイプ。  

void ProcessItem const ItemType i { //コレクションの各アイテムを処理する関数。std :: cout << i << std :: endl ;     
      
}

std :: for_each c .begin ( )、c .end )、ProcessItem ; //for-each反復ループ。   

同じことは、3番目のイテレータとして値を std::copy渡すを使用して実現できます。std::ostream_iterator

std :: copy c .begin ()、c .end )、std :: ostream_iterator < ItemType > std :: cout " \ n " ));   

C ++ 11以降ラムダ関数構文を使用して、インラインで繰り返される操作を指定できるため、名前付き関数を定義する必要がなくなります。ラムダ関数を使用したfor-each反復の例を次に示します。

ContainerType < ItemType > c ; //ItemType要素の標準コンテナタイプ。  

//ラムダ関数を使用したfor-each反復ループ。
std :: for_each c .begin ()、c .end )、[](const ItemType i { std :: cout << i << std :: endl ; } );           

Java

Java JDK 1.2リリースで導入されたjava.util.Iteratorインターフェースにより、コンテナークラスの反復が可能になります。それぞれがメソッドをIterator提供し、オプションnext()でメソッドhasNext()をサポートする場合がありますremove()イテレータは、対応するコンテナクラスによって、通常は。という名前のメソッドによって作成されiterator()ます。[15]

このnext()メソッドはイテレーターを進め、イテレーターが指す値を返します。最初の要素は、への最初の呼び出しで取得されnext()ます。コンテナ内のすべての要素がいつ訪問されたかを判断するために、hasNext()テストメソッドが使用されます。次の例は、イテレータの簡単な使用法を示しています。

イテレータ iter  =  list イテレータ(); 
// Iterator <MyType> iter = list.iterator(); // J2SE 5.0では
while  iter .hasNext ( { System アウトprint iter .next )); if iter .hasNext ( System アウト印刷"、" ); } 
    
     
        

これを繰り返し呼び出すことができることを示すためhasNext()に、要素の間にコンマを挿入しますが、最後の要素の後には挿入しません。

このアプローチでは、事前操作を実際のデータアクセスから適切に分離しません。データ要素をアドバンスごとに複数回使用する必要がある場合は、一時変数に格納する必要があります。データアクセスなしでアドバンスが必要な場合(つまり、特定のデータ要素をスキップするため)、それでもアクセスは実行されますが、この場合、戻り値は無視されます。

それをサポートするコレクションタイプの場合、イテレータのremove()メソッドは、イテレータを使用可能な状態に保ちながら、最後にアクセスした要素をコンテナから削除します。コンテナのメソッドを(同じスレッドからも)呼び出して要素を追加または削除すると、イテレータが使用できなくなります。次の要素を取得しようとすると、例外がスローされます。hasNext()残りの要素がない場合(以前はfalseを返した 場合)にも例外がスローされます。

さらに、同様のAPIを備えたjava.util.Listがありjava.util.ListIteratorますが、これにより、順方向と逆方向の反復が可能になり、リスト内の現在のインデックスが提供され、リスト要素をその位置に設定できます。

JavaのJ2SE5.0リリースでは、コレクションと配列を反復処理するIterableための拡張forforeach)ループをサポートするインターフェイスが導入されました。を返すメソッドをIterable定義します拡張ループを使用すると、前の例を次のように書き直すことができます。 iterator()Iteratorfor

for  MyType  obj   list  { 
    System アウト印刷obj ); 
}

一部のコンテナは、古い(1.0以降)Enumerationクラスも使用します。メソッドを提供hasMoreElements()nextElement()ますが、コンテナを変更するメソッドはありません。

Scala

Scalaでは、イテレーターにはコレクションと同様の豊富なメソッドセットがあり、forループで直接使用できます。実際、イテレータとコレクションはどちらも共通の基本特性を継承しています- scala.collection.TraversableOnceただし、、などのScalaコレクションライブラリで利用できるメソッドの豊富なセットのため、Scalamapcollectプログラミングfilterするときにイテレータを直接処理する必要がないことがよくあります。

Javaイテレーターとコレクションは、1行追加するだけで、それぞれScalaイテレーターとコレクションに自動的に変換できます。

インポート scala コレクションJavaConversions _

ファイルに。オブジェクトは、これを行うためのJavaConversions暗黙的な変換を提供します。暗黙の変換はScalaの機能です。現在のスコープに表示されている場合、メソッドは、適切な場所で関連する式に自動的に呼び出しを挿入し、そうでない場合はタイプチェックを行います。

MATLAB

MATLABは、「ネイティブ」配列またはcell配列のいずれかを使用して、外部と内部の両方の暗黙的な反復をサポートします。トラバーサルを進めて次の要素を要求する責任がユーザーにある外部反復の場合、配列ストレージ構造内で要素のセットを定義し、-loop構造を使用して要素をトラバースすることができますfor例えば、

%整数の配列を定義する
myArray = [ 1、3、5、7、11、13 ] ; _ _ _ _ _ _ _ _ _  

n = myArrayの場合   
   %...nで何かをする
   disp n %コマンドウィンドウに整数をエコー  
終わり

forキーワード を使用して整数の配列をトラバースします。

ユーザーがコレクションのすべての要素に対して実行する操作をイテレーターに提供できる内部反復の場合、多くの組み込み演算子とMATLAB関数がオーバーロードされて、配列のすべての要素に対して実行され、対応する出力配列が暗黙的に返されます。 。さらに、arrayfunおよびcellfun関数を利用して、それぞれ「ネイティブ」配列およびcell配列に対してカスタムまたはユーザー定義の操作を実行できます。例えば、

関数simpleFun 
%整数の配列を定義する
myArray = [ 1、3、5、7、11、13 ] ; _ _ _ _ _ _ _ _ _  

%各要素に対してカスタム操作を実行します
myNewArray = arrayfun (@(a myCustomFun a )、myArray );  

%結果の配列をコマンドウィンドウにエコーします
myNewArray

関数outScalar = myCustomFun inScalar    
%単純に2を掛ける
outScalar = 2 * inScalar ;  

組み込み関数を使用して、配列の各要素にsimpleFunカスタムサブ関数を暗黙的に適用するプライマリ関数を定義しますmyCustomFunarrayfun

あるいは、イテレータパターンのカスタムオブジェクト指向MATLAB実装を定義することにより、ユーザーから配列ストレージコンテナのメカニズムを抽象化することが望ましい場合があります。外部反復をサポートするこのような実装は、MATLAB Central File Exchangeアイテムのデザインパターン:イテレーター(動作)で示されています。これは、MATLABソフトウェアバージョン7.6(R2008a)で導入された新しいクラス定義構文で記述され、異種(データ型)セットを格納するメカニズムとして、リスト抽象データ型(ADT)の1次元cell配列実現を特徴としています。要素。これは、を使用した明示的なフォワードリストトラバーサルの機能と、使用するメソッドを提供します。hasNext()next()reset()while-ループ。

PHP

PHPforeachループはバージョン4.0で導入され、4.0 Beta 4の値としてオブジェクトと互換性があります。[16]ただし、内部[17] Traversableインターフェースの導入により、PHP5でイテレーターのサポートが追加されました。[18]foreachループをIterator介してオブジェクトを反復できるようにするPHPスクリプトで実装するための2つの主要なインターフェースはとIteratorAggregateです。後者は、実装クラスが必要なすべてのメソッドを宣言する必要はありません。代わりに、のインスタンスを返すアクセサメソッド( )を実装します標準PHPライブラリには、特別なイテレータを操作するためのいくつかのクラスが用意されています[19]getIteratorTraversablePHPは、5.5以降のジェネレーターもサポートしています。[20]

最も単純な実装は、配列をラップすることです。これは、型のヒント情報の隠蔽に役立ちます。

名前空間 Wikipedia\Iterator ;

最終 クラス ArrayIterator  \Iterator 
{
    プライベート 配列 $array ;を拡張します。

    public  function  __construct array  $ array 
    { 
        $ this- > array  =  $ array ; 
    }

    public  function  rewind () void 
    { 
        echo  '巻き戻し'   PHP_EOL ; 
        リセット$ this- > array ); 
    }

    public  function  current ()
    { 
        $ value  =  current $ this- > array ); 
        echo  "current:{ $ value } "  PHP_EOL ; 
        $valueを返します ; }
    

    パブリック ファンクション キー()
    { 
        $ key  =  key $ this- > array ); 
        echo  "key:{ $ key } "  PHP_EOL ; 
        $keyを返します ; }
    

    public  function  next ()
    { 
        $ value  =  next $ this- > array ); 
        echo  "next:{ $ value } "  PHP_EOL ; 
        $valueを返します ; }
    

    public  function  valid () bool 
    { 
        $ valid  =  $ this- > current () !==  false ; 
        echo'valid  :'  $ valid   'true'   'false' )、 PHP_EOL ; 
        $validを返します ; } }
    

サンプルクラスのすべてのメソッドは、完全なforeachループ(foreach ($iterator as $key => $current) {})の実行中に使用されます。イテレータのメソッドは、次の順序で実行されます。

  1. $iterator->rewind()内部構造が最初から始まることを保証します。
  2. $iterator->valid()この例ではtrueを返します。
  3. $iterator->current()戻り値はに格納され$valueます。
  4. $iterator->key()戻り値はに格納され$keyます。
  5. $iterator->next()内部構造の次の要素に進みます。
  6. $iterator->valid()falseを返し、ループは中止されます。

次の例は、インターフェイスを実装するPHPクラスを示しています。このクラスは、ループに返される前にデータに作用するクラスにTraversableラップされる可能性があります。定数と一緒に使用することで、PHPスクリプトは、メモリ使用量が非常に少ない数十億行の結果セットを繰り返すことができます。これらの機能は、PHPまたはそのMySQLクラスの実装に限定されていません(たとえば、クラスはインターフェイスも実装します)。 IteratorIteratorforeachMYSQLI_USE_RESULTPDOStatementTraversable

mysqli_report MYSQLI_REPORT_ERROR  |  MYSQLI_REPORT_STRICT ); 
$ mysqli  =  new  \ mysqli 'host.example.com'  'username'  'password'  'database_name' );

//メソッド呼び出しによって返される\mysqli_resultクラスは、内部Traversableインターフェースを実装します。
foreach  $ mysqli- > query 'SELECT `a`、` b`、 `c` FROM` table`'  MYSQLI_USE_RESULT  as  $ row  { 
    //連想配列である返された行に作用します。
}

Python

Pythonのイテレータは言語の基本的な部分であり、 forforeach)ステートメント、リスト内包表記、およびジェネレータ式で暗黙的に使用されるため、多くの場合、見えなくなりますPythonのすべての標準組み込みコレクションタイプは、標準ライブラリの一部である多くのクラスと同様に、反復をサポートします。次の例は、シーケンスに対する一般的な暗黙の反復を示しています。

 シーケンス の場合 print value 
    

Python辞書(連想配列の形式)は、辞書キーが返されるときに直接繰り返すこともできます。または、items()ディクショナリのメソッドを繰り返して、対応するキーと値のペアをタプルとして生成することもできます。

 辞書キー の場合 value = dictionary [ key ] print key value 
      
     
 キーの場合辞書  items ():print key value  
     

ただし、イテレータは明示的に使用および定義できます。反復可能なシーケンスタイプまたはクラスの場合、組み込み関数iter()を使用してイテレータオブジェクトを作成します。次に、イテレータオブジェクトは、コンテナ内の次の要素を返すメソッドを内部的にnext()使用する関数で反復できます。__next__()(前のステートメントはPython 3.xに適用されます。Python2.xでは、next()メソッドは同等です。)StopIteration要素がなくなると例外が発生します。次の例は、明示的なイテレータを使用したシーケンスに対する同等の反復を示しています。

it  =  iter sequence 
while  True 
    try 
        value  =  it next () # Python2.xの
        場合value  =  next it ) #Python  3.xの場合
    StopIterationを除く break print value 
        
    

__iter__()すべてのユーザー定義クラスは、イテレーターオブジェクトを返すメソッドを定義することにより、標準の反復(暗黙的または明示的)をサポートできます。次に、イテレータオブジェクト__next__()は、次の要素を返すメソッドを定義する必要があります。

Pythonのジェネレーターは、この反復プロトコルを実装します。

Rakuのイテレータは言語の基本的な部分ですが、通常、ユーザーはイテレータを気にする必要はありません。forそれらの使用法は、ステートメントmap、、、grepリストのインデックス付けなどの反復APIの背後に隠されています.[$idx]

次の例は、値のコレクションに対する一般的な暗黙の反復を示しています。

 @
 values = 1、2、3 ; _ _ @values- > $ value {
     say $ value  
}
#出力:
#1 
#2 
#3

Rakuハッシュは直接繰り返すこともできます。これにより、キー値Pairオブジェクトが生成されます。このkvメソッドはハッシュで呼び出して、キーと値を反復処理できます。keysハッシュのキーを反復処理するメソッドvaluesハッシュの値を反復処理するメソッド

私の %word-to-number = 'one' => 1'two' => 2'three' => 3 ;
for  %word-to-number- > $ pair {
     say  $ pair ;
}
#出力:
#3 => 3 
#1 => 1 
#2 => 2

 %word-to-numberの場合kv- > $ key$ value {
     say  "$ key:$ value" 
}
#出力:
#3:3 
#1:1 
#2:2

 %word-to-numberの場合キー-> $key {
     say  "$ key =>"%word-to-number { $ key };
}
#出力:
#3 => 3 
#1 => 1 
#2 => 2

ただし、イテレータは明示的に使用および定義できます。反復可能なタイプの場合、反復プロセスのさまざまな側面を制御するいくつかの方法があります。たとえば、メソッドはオブジェクトiteratorを返すことになっており、メソッドは可能であれば次の値を生成して返すか、それ以上値を生成できない場合は番兵の値を返すことになっています。次の例は、明示的なイテレータを使用したコレクションに対する同等の反復を示しています。 Iteratorpull-oneIterationEnd

 @
 values = 1、2、3 ; _ _ 私の$it  := @valuesイテレータ;          #@valuesのイテレータを取得します 

loop {
     my  $ value  := $itプルワン;       
    $ value =:= IterationEnd ;の場合、反復の次の値を最後に取得します。 #反復の終わりに達した場合は停止しますsay $ value ; 
     
}
#出力:
#1 
#2 
#3

Rakuのすべての反復可能なタイプは、Iterable役割、Iterator役割、またはその両方を構成します。Iterable非常に単純でiterator、作成クラスによって実装する必要があるだけです。Iteratorはより複雑で、などの一連のメソッドを提供しますpull-oneこれにより、アイテムの追加や削除、他のアイテムへのアクセスのためのスキップなど、いくつかのコンテキストでの反復のより細かい操作が可能になります。したがって、任意のユーザー定義クラスは、これらのロールを構成し、iteratorおよび/またはpull-oneメソッドを実装することにより、標準の反復をサポートできます。

クラスはDNADNA鎖を表し、役割iteratorを構成することによってを実装します。IterableDNA鎖は、次のように繰り返されると、トリヌクレオチドのグループに分割されます。

 StrサブセットStrandwhere  { 一致/ ^^ <[ACGT]> + $$ /およびchars  %% 3 };
クラスDNAIterableを行います{
    $.chainを持っています;
    メソッドnewStrand:D $ chain){
         self祝福::  $ chain        
    }
 
    メソッド イテレータDNA:D:){ $.chainくしローター3)。イテレータ}
};

 DNAの場合new'GATTACATA'){いう
}
#出力:
#(GAT)
#(TAC)
#(ATA)

 DNAと言います。new'GATTACATA')。マップ(* 。join)。参加'-');
#出力:
#GAT-TAC-ATA

Repeaterクラスはとの両方の役割を構成IterableますIterator

class  Repeater  does  Iterable  does  Iterator {
     has  Any  $ .item   is  required ;
    Int $.times 必要です;
    Int $!count = 1 ;があります。     
    
    マルチ メソッド new$ item$ times){
         self祝福::  $ item、:$ times ;
    }
    
    メソッド イテレータ{ self }
    メソッド pull-one(-> Mu){ 
         if  $!count <= $!times {
             $!count + = 1 ;
            $!itemを返す 
        }
        else {
             return  IterationEnd
        }
    }
}

 リピーターnew"Hello"3){いう
}

#出力:
#こんにちは
#こんにちは
#こんにちは

ルビー

Rubyはイテレータをまったく異なる方法で実装します。すべての反復は、コールバッククロージャをコンテナメソッドに渡すことによって実行されます。このようにして、Rubyは基本的な反復だけでなく、関数のマッピング、フィルター、リダクションなどの反復のいくつかのパターンも実装します。Rubyは、基本的な反復方法の代替構文もサポートしていますeach。次の3つの例は同等です。

0 ... 42 それぞれ が行う | n | 
  nを 終了します

...と...

for  n  in  0 ... 42 
  puts  n 
end

またはさらに短い

42 時間  | n | 
  nを 終了します

Rubyは、上記のように、sを使用し、それらのメソッド Enumeratorを呼び出すか、それぞれに対してaを実行することにより、固定リストを反復処理することもできます。#next

さび

Rustを使用すると、ベクトルの要素を反復したり、独自のイテレータを作成したりできます。map各イテレータにfilterアダプタ(、、、、、...)があります skiptake

n in 0 .. 42 { _    
    println!"{}" n ); 
}

以下のfibonacci()関数は、カスタムイテレータを返します。

フィボナッチのために()。スキップ4 )。取る4 {    
    println!"{}" i ); 
}

も参照してください

参照

  1. ^ ガットコム、ジョシュア。「イテレータの理解と使用」Perl.com。2005年6月16日にオリジナルからアーカイブされまし2012年8月8日取得ユーザー定義のイテレータは通常、実行時にリスト内の次の項目を計算して返すコード参照の形式を取ります。イテレータがリストの最後に到達すると、合意された値を返します。
  2. ^ a b Watt、Stephen M. 「一般的な反復とその最適化の手法」(PDF)ウエスタンオンタリオ大学、コンピュータサイエンス学部。2006年9月16日にオリジナル(PDF)からアーカイブされました2012年8月8日取得イテレータは、内部表現を明らかにすることなく抽象データ構造をループできるようにするための構造として導入されました。
  3. ^ アレックスアラン。「STLイテレータ」Cprogramming.com-CおよびC++のリソース2012年8月8日取得イテレータは、アイテムのより大きなコンテナの一部であるアイテムを指していると考えることができます。
  4. ^ ab "外部イテレータと内部イテレータ 違い"CareerRide.COM。2009-04-03。2009年4月3日にオリジナルからアーカイブされました。2012年8月8日取得内部イテレータは、反復ロジックを持つクラスのメンバー関数によって実装されます。外部イテレータは、反復ロジックを持つオブジェクトにアタッチできる別のクラスによって実装されます。外部イテレータの利点は、既存または同じオブジェクトに対して同時に多くのイテレータをアクティブにできることです。
  5. ^ Watt、Stephen M. 「一般的な反復とその最適化の手法」(PDF)ウエスタンオンタリオ大学、コンピュータサイエンス学部。2006年9月16日にオリジナル(PDF)からアーカイブされました2012年8月8日取得イテレータという用語を使用する作成者もいれば、ジェネレータという用語を使用する作成者もいます。2つを微妙に区別するものもあります。
  6. ^ a b フリーマン、エリック; フリーマン、エリザベス; キャシー、シエラ; バート、ベイツ(2004)。ヘンドリクソン、マイク; ルーキデス、マイク(編)。「ヘッドファーストデザインパターン」(ペーパーバック)1オライリー: 338。ISBN  978-0-596-00712-62012年8月9日取得 {{cite journal}}引用ジャーナルには|journal=ヘルプ)が必要です
  7. ^ 「用語集—Python3.8.4ドキュメント」2020年7月15日取得
  8. ^ Vecerina、Ivan(2006-02-01)。「インデックスとイテレータ」バイト。2006-02-01にオリジナルからアーカイブされました2012年8月8日取得インデックスは、ランダムアクセス(つまり、特定の位置にある要素への直接アクセス)を(効率的に)サポートするコンテナーにのみ使用できます。イテレータは、より一般的な概念です。イテレータは、リンクリスト、ファイル、およびその他の多くのデータ構造の効率的なトラバーサルを提供します。多くの場合、より効率的なコードの生成につながります。
  9. ^ ケビンウォーターソン。「C++Iteratoren:Iterator-Kategorien」(ドイツ語)。cppreference.com 2012年8月9日取得
  10. ^ ケビンウォーターソン。「イテレータ:概念」sgi 2012年8月9日取得
  11. ^ larsmans(2011-03-06)。「イテレータのタイプ:出力vs.入力vs.フォワードvs.ランダムアクセスイテレータ」スタックオーバーフロー。2011年3月6日にオリジナルからアーカイブされました2012年8月9日取得
  12. ^ ケビンウォーターソン。「SPLの概要:標準PHPライブラリ(SPL)の概要」PHPRO.ORG 2012年8月9日取得
  13. ^ コリアー、アンドリュー。「Rのイテレータ」2018年10月18日にオリジナルからアーカイブされました2013年11月16日取得
  14. ^ "concurrent_unordered_setテンプレートクラス"オープンソース向けのインテルスレッディングビルディングブロック。2015年5月1日にオリジナルからアーカイブされました2012年8月9日取得•イテレータタイプiteratorおよびconst_iteratorは、フォワードイテレータカテゴリです。
  15. ^ "java.util:インターフェイスイテレータ<E>:メソッドの概要"Oracle 2012年8月8日取得
  16. ^ 「PHP4ChangeLog」PHPグループ。2000-02-20 2015年10月13日取得
  17. ^ 内部とは、インターフェイスをPHPスクリプトで実装できず、 C(プログラミング言語)ソースでのみ実装できることを指します。
  18. ^ 「トラバース可能なインターフェース」PHPグループ2015年10月13日取得
  19. ^ 「イテレータ」PHPグループ2015年10月13日取得
  20. ^ 「PHP5ChangeLog」PHPグループ。2013-06-20 2015年10月13日取得

外部リンク