29

PHP 5.2で配列を反復処理しながら「先読み」することは可能ですか?たとえば、配列からのデータを操作するためにforeachをよく使用します。

foreach($array as $object) {
  // do something
}

しかし、配列を調べている間、次の要素をのぞく必要があることがよくあります。forループを使用して、インデックス()で次の項目を参照できることはわかっています$array[$i+1]が、連想配列では機能しません。おそらくSPLを含む、私の問題に対するエレガントな解決策はありますか?

4

6 に答える 6

56

この目的でCachingIteratorを使用できます。

次に例を示します。

$collection = new CachingIterator(
                  new ArrayIterator(
                      array('Cat', 'Dog', 'Elephant', 'Tiger', 'Shark')));

CachingIteratorは、常に内部イテレータの1つ後ろにあります。

var_dump( $collection->current() ); // null
var_dump( $collection->getInnerIterator()->current() ); // Cat

したがって、foreachやり直す$collectionと、内側のArrayIteratorの現在の要素がすでに次の要素になり、それを覗き見できるようになります。

foreach($collection as $animal) {
     echo "Current: $animal";
     if($collection->hasNext()) {
         echo " - Next:" . $collection->getInnerIterator()->current();
     }
     echo PHP_EOL;
 }

出力します:

Current: Cat - Next:Dog
Current: Dog - Next:Elephant
Current: Elephant - Next:Tiger
Current: Tiger - Next:Shark
Current: Shark

説明できない理由で、CachingIteratorは常に現在の要素を文字列に変換しようとします。オブジェクトコレクションを反復処理し、メソッドのプロパティにアクセスする必要がある場合はCachingIterator::TOSTRING_USE_CURRENT、2番目のパラメーターとしてコンストラクターに渡します。


ちなみに、CachingIteratorは、これまでに繰り返したすべての結果をキャッシュする機能からその名前を取得します。これを機能させるには、でインスタンス化する必要がCachingIterator::FULL_CACHEあります。その後、でキャッシュされた結果をフェッチできますgetCache()

于 2010-03-16T21:04:11.137 に答える
20

を使用しarray_keysます。

$keys = array_keys($array);
for ($i = 0; $i < count($keys); $i++) {
    $cur = $array[$keys[$i]];
    $next = $array[$keys[$i+1]];
}
于 2010-03-16T21:05:14.880 に答える
8

配列を使用nextprevて反復することができます。current現在のアイテムの値とkey現在のキーを返します。

したがって、次のようなことができます。

while (key($array) !== null) {
    next($array); // set pointer to next element
    if (key($array) === null) {
        // end of array
    } else {
        $nextItem = current($array);
    }
    prev($array); // resetting the pointer to the current element

    // …

    next($array);
}
于 2010-03-16T21:03:01.333 に答える
4

これが古い投稿であることは知っていますが、現在/次/前のことを今よりよく説明できます。例:

$array = array(1,2,3,2,5);

foreach($array as $k => $v) {
    // in foreach when looping the key() and current() 
    // is already pointing to the next record
    // And now we can print current
    print 'current key: '.$k.' and value: '.$v;
    // if we have next we can print its information too (key+value)
    if(current($array)) {
         print ' - next key: '.key($array).' and value: '.current($array);
         // at the end we must move pointer to next
         next($array);
    }
    print '<br>';
}

// prints:
// current key: 0 and value: 1 - next key: 1 and value: 2
// current key: 1 and value: 2 - next key: 2 and value: 3
// current key: 2 and value: 3 - next key: 3 and value: 2
// current key: 3 and value: 2 - next key: 4 and value: 5
// current key: 4 and value: 5
于 2012-09-17T19:35:10.063 に答える
0

forループを使用して、そのインデックス($ array [$ i + 1])で次の項目を参照できることはわかっていますが、連想配列では機能しません。

連想配列をarray_values()を使用して順次インデックス付けされた配列に変換することを検討してください。これにより、単純なforループソリューションを使用できるようになります。

于 2013-03-12T16:05:01.797 に答える
0

古い投稿ですが、私の2セント:

あなたが先を覗き見しようとしているなら、あなたは本当に「私はこの問題を可能な限り最善の方法で解決しているのか」と自問する必要があります。

先読みを行うことなく、すべての先読み問題を解決できます。必要なのは、コレクションの前に宣言された「$ prevItem」参照であり、それをnullとして初期化します。ループを通過するたびに、最後に、$prevItemを評価したばかりの現在の配列アイテムに設定します。事実上、先にピークを迎える代わりに、2番目の項目で実際のロジックの実行を開始し、$prevItem参照を使用して操作を実行します。$ prevItemがnullであることに注意して、最初の項目をスキップします。

$prevItem = null;
$prevKey = null;

foreach($collection as $key => $val)
{
     if($prevItem != null)
     {
          //do your operation here
     }


     $prevItem = $val;
     $prevKey = $key;
}

クリーンなコードとその一般的なパターンです。

基礎となるデータ構造を反復処理している間は、それらをいじくり回さないでください...決して良い習慣ではなく、それを行う必要があることは非常にまれです。

于 2020-07-10T20:06:42.873 に答える