【PHP8.x】LimitIterator::seek()メソッドの使い方
seekメソッドの使い方について、初心者にもわかりやすく解説します。
基本的な使い方
seekメソッドは、LimitIteratorオブジェクトが指し示す現在の要素の位置を、指定した位置へ移動させるために実行するメソッドです。LimitIteratorは、元のイテレータの一部分を切り取って反復処理を行いますが、seekメソッドはこの切り取られた範囲内での位置を指定します。引数として0から始まる整数値を指定すると、イテレータのポインタがその位置に移動します。例えば、引数に1を指定した場合、切り取られた範囲の2番目の要素へ移動します。内部的には、元のイテレータに対して「LimitIterator作成時に指定したオフセット + seekメソッドで指定した位置」の場所へ移動する処理が行われます。もし、指定した位置がLimitIteratorで定められた有効な範囲の外であった場合、OutOfBoundsExceptionという例外が発生するため注意が必要です。このメソッドは、イテレータの特定の部分集合の中から、さらに特定の位置の要素に直接アクセスしたい場合に役立ちます。
構文(syntax)
1<?php 2 3$array = ['A', 'B', 'C', 'D', 'E', 'F', 'G']; 4$arrayIterator = new ArrayIterator($array); 5 6// 配列のインデックス2から3要素分 ('C', 'D', 'E') に制限します 7$limitIterator = new LimitIterator($arrayIterator, 2, 3); 8 9// 制限された範囲内のインデックス1 (2番目の要素 'D') に移動します 10$limitIterator->seek(1); 11 12// 現在位置のキーと値を出力します 13// seek()で指定した位置は元の配列のキーとは異なることに注意してください 14echo 'Key: ' . $limitIterator->key() . PHP_EOL; // 出力: Key: 3 15echo 'Value: ' . $limitIterator->current() . PHP_EOL; // 出力: Value: D 16 17?>
引数(parameters)
int $position
- int $position: 移動したい位置を指定する整数
戻り値(return)
int
指定された位置にイテレータを移動させた後の、現在のイテレータの位置(インデックス)を返します。
サンプルコード
LimitIterator で seek を使う
1<?php 2 3/** 4 * LimitIteratorとSeekableIterator::seekの使用例 5 * 6 * このサンプルコードは、イテレータの一部を切り出すLimitIteratorで、 7 * SeekableIteratorインターフェースのseek()メソッドを使い、 8 * 特定の位置に直接移動する方法を示します。 9 */ 10function demonstrateLimitIteratorSeek(): void 11{ 12 // 1. 元となるデータソース(配列) 13 $data = [ 14 'a' => 'Apple', 15 'b' => 'Banana', 16 'c' => 'Cherry', // LimitIteratorの開始点 (オフセット 2) 17 'd' => 'Date', 18 'e' => 'Elderberry', 19 'f' => 'Fig', // この範囲の最後の要素 (カウント 4) 20 'g' => 'Grape', 21 ]; 22 23 // 2. 配列からSeekableなArrayIteratorを作成します 24 $arrayIterator = new ArrayIterator($data); 25 26 // 3. ArrayIteratorの一部を扱うLimitIteratorを作成します 27 // オフセット 2 ('Cherry') から 4 つの要素を対象とします 28 // 対象範囲: ['c' => 'Cherry', 'd' => 'Date', 'e' => 'Elderberry', 'f' => 'Fig'] 29 $limitIterator = new LimitIterator($arrayIterator, 2, 4); 30 31 echo "--- LimitIteratorの対象範囲 ---" . PHP_EOL; 32 foreach ($limitIterator as $key => $value) { 33 // getPosition()はLimitIterator内での相対的な位置 (0から始まる) を返します 34 // key()は元のイテレータのキーを返します 35 echo sprintf( 36 "Position: %d, Key: %s, Value: %s" . PHP_EOL, 37 $limitIterator->getPosition(), 38 $key, 39 $value 40 ); 41 } 42 echo PHP_EOL; 43 44 // 4. seek()メソッドでLimitIterator内の特定の位置(position)に移動します 45 // LimitIteratorのインデックスは0から始まります。 46 // seek(2)は、対象範囲内の3番目の要素 ('Elderberry') を指します。 47 $positionToSeek = 2; 48 echo "--- seek({$positionToSeek}) を実行 ---" . PHP_EOL; 49 50 // seek()を実行します。このメソッドはSeekableIteratorインターフェースで定義されています。 51 $limitIterator->seek($positionToSeek); 52 53 // 5. seek()後の現在の要素を確認します 54 if ($limitIterator->valid()) { 55 echo "seek() 後の現在地:" . PHP_EOL; 56 echo sprintf( 57 "Position: %d, Key: %s, Value: %s" . PHP_EOL, 58 $limitIterator->getPosition(), 59 $limitIterator->key(), 60 $limitIterator->current() 61 ); 62 } else { 63 echo "位置 {$positionToSeek} は範囲外のため、移動できませんでした。" . PHP_EOL; 64 } 65} 66 67// 関数を実行して結果を表示します 68demonstrateLimitIteratorSeek();
LimitIterator::seek()は、イテレータの内部ポインタ(現在位置)を、指定した位置へ直接移動させるためのメソッドです。この機能は SeekableIterator インターフェースで定義されており、LimitIterator はこのインターフェースを実装しているため seek() を呼び出すことができます。
引数 $position には、移動したい位置を0から始まる整数で指定します。この位置は、LimitIterator が元のイテレータから切り取った範囲内での相対的なインデックスです。元のデータのキーやオフセットとは異なる点に注意が必要です。PHP 8以降、このメソッドは値を返さない(void)ため、指定した位置が有効範囲内にあるかは、seek() 実行後に valid() メソッドを使って確認します。
サンプルコードでは、配列から作成した ArrayIterator の一部(オフセット2から4要素)を LimitIterator で扱います。ここで seek(2) を実行すると、この切り出された範囲内の0から数えて2番目、つまり3番目の要素である 'Elderberry' の位置へポインタが移動します。移動後は、current() メソッドでその要素の値を取得できます。
LimitIteratorのseekメソッドを使う際の最も重要な注意点は、引数で指定する位置が、元のデータ全体ではなく、LimitIteratorで切り出した範囲内での0から始まる相対的なインデックスであることです。元のデータのキーや全体での位置と混同しないようにしましょう。このseek機能は、内部のイテレータがSeekableIteratorインターフェースを実装している場合にのみ有効です。実装していないイテレータを渡すとエラーになります。また、範囲外の位置へseekするとイテレータは無効になるため、実行後はvalid()メソッドで有効性を確認してから値にアクセスするのが安全な使い方です。
LimitIterator::seekで最後の要素に移動する
1<?php 2 3/** 4 * LimitIterator::seek を使ってイテレータの最後の要素に移動する例 5 * 6 * キーワード `seek_end` は、最後の要素への移動を意図していると解釈し、 7 * イテレータが扱う要素数を元に最後の位置を計算して seek() を実行します。 8 */ 9function demonstrateLimitIteratorSeekEnd(): void 10{ 11 // 1. 元となるデータの配列 12 $fruits = ['Apple', 'Banana', 'Cherry', 'Durian', 'Elderberry', 'Fig', 'Grape']; 13 14 // 2. 配列から ArrayIterator を作成 15 $arrayIterator = new ArrayIterator($fruits); 16 17 // 3. ArrayIterator の一部分のみを扱う LimitIterator を作成 18 // この例では、インデックス 2 ('Cherry') から 4 つの要素を対象とします。 19 // 対象範囲: ['Cherry', 'Durian', 'Elderberry', 'Fig'] 20 $limitIterator = new LimitIterator($arrayIterator, 2, 4); 21 22 // 4. LimitIterator が実際に扱う要素の数を取得 23 // iterator_count() はイテレータを最後まで進めるため、後で巻き戻しが必要です。 24 $count = iterator_count($limitIterator); 25 $limitIterator->rewind(); // イテレータを先頭に戻す 26 27 // 5. 最後の要素のインデックスを計算 (0から始まるため、要素数 - 1) 28 // 要素数が 4 の場合、最後のインデックスは 3 29 if ($count > 0) { 30 $lastPosition = $count - 1; 31 32 // 6. seek() メソッドで最後の要素の位置に移動 33 $limitIterator->seek($lastPosition); 34 35 // 7. 現在の要素 (最後の要素) を取得して表示 36 echo "対象範囲: ['Cherry', 'Durian', 'Elderberry', 'Fig']" . PHP_EOL; 37 echo "最後の要素の位置 ($lastPosition) に移動しました。" . PHP_EOL; 38 echo "最後の要素: " . $limitIterator->current() . PHP_EOL; 39 } else { 40 echo "LimitIterator の対象範囲に要素はありません。" . PHP_EOL; 41 } 42} 43 44// 関数を実行します 45demonstrateLimitIteratorSeekEnd(); 46
LimitIterator::seekメソッドは、LimitIteratorが扱う要素の範囲内で、指定した位置に内部ポインタを移動させる機能を提供します。
サンプルコードは、このseekメソッドを使って対象範囲内の「最後の要素」に移動する手順を示したものです。PHPのseekメソッドには直接最後の要素を指定する定数などがないため、まずiterator_count関数を使ってLimitIteratorが実際に扱っている要素の総数を取得します。iterator_count関数は内部でイテレータを最後まで進めてしまうため、実行後にはrewindメソッドでポインタを先頭に戻す必要があります。
次に、取得した要素数から1を引くことで、0から始まるインデックスにおける最後の要素の位置を計算します。この計算結果をseekメソッドの引数$positionに渡すことで、ポインタを目的の最後の要素へ正確に移動させることができます。引数$positionには、移動したい位置を0から始まる整数で指定します。PHP 8のseekメソッドは値を返さない仕様(戻り値はvoid)です。
LimitIterator::seek()で指定する位置は、元のデータ全体の通し番号ではなく、LimitIteratorで絞り込んだ範囲内での0から始まる相対的な位置です。この点を混同しないよう注意が必要です。また、最後の要素に移動するために要素数をiterator_count()で取得していますが、この関数はイテレータを最後まで進めてしまう副作用があります。そのため、seek()を正しく機能させるには、iterator_count()の直後にrewind()を呼び出し、イテレータを先頭に戻す処理が不可欠です。対象範囲に要素がない場合に備え、要素数が0より大きいことを確認してからseek()を実行すると、より安全なコードになります。