Pergunta

É possível "espiar adiante" enquanto itera um array no PHP 5.2?Por exemplo, costumo usar foreach para manipular dados de um array:

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

Mas muitas vezes preciso dar uma olhada no próximo elemento enquanto percorro o array.Eu sei que poderia usar um for faça um loop e faça referência ao próximo item por seu índice ($array[$i+1]), mas não funcionaria para matrizes associativas.Existe alguma solução elegante para o meu problema, talvez envolvendo SPL?

Foi útil?

Solução

Você pode usar o Cacharerator para esse fim.

Aqui está um exemplo:

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

O cacachingiterator está sempre um passo atrás do iterador interno:

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

Assim, quando você faz foreach sobre $collection, o elemento atual do ArrayIterator interno já será o próximo elemento, permitindo que você espie nele:

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

Será lançado:

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

Por alguma razão, não posso explicar, o cacheingiterator sempre tentará converter o elemento atual em string. Se você deseja iterar sobre uma coleção de objetos e precisa acessar as propriedades de um método, passe CachingIterator::TOSTRING_USE_CURRENT como o segundo parâmetro para o construtor.


Em uma sidenote, o cacachingiterator recebe seu nome da capacidade de armazenar em cache todos os resultados que ele iterou até agora. Para que isso funcione, você precisa instanciá -lo com CachingIterator::FULL_CACHE E então você pode buscar os resultados em cache com getCache().

Outras dicas

Usar array_keys.

$keys = array_keys($array);
for ($i = 0; $i < count($keys); $i++) {
    $cur = $array[$keys[$i]];
    $next = $array[$keys[$i+1]];
}

Você pode usar next e prev para itera uma matriz. current Retorna o valor dos itens atuais e key a chave atual.

Então você poderia fazer algo assim:

while (key($array) !== null) {
    next($array);
    if (key($array) === null) {
        // end of array
    } else {
        $nextItem = value($array);
    }
    prev($array);

    // …

    next($array);
}

Sei que este é um post antigo, mas posso explicar que a coisa atual/a seguir/prev é melhor agora. Exemplo:

$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

Eu sei que poderia usar um loop for e referenciar o próximo item por seu índice ($array[$i+1]), mas não funcionaria para arrays associativos.

Considere converter sua matriz associativa em uma indexada sequencialmente com array_valores(), permitindo que você use a solução for loop simples.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top