Lelio Faieta
Lelio Faieta

Reputation: 6673

preview next array element using foreach

I have a foreach that iterates between items in a array to build an excel file. I want to place a total row after each item in the array if the next element in the array matches a specific condition (has a specific value in one key). So I want to use next() to check that value but as far as I know and for what I read here using next I'll move the pointer to the next row and the answer was to use current. How can I see the next item in the array without moving the pointer? reading that question I have written this:

foreach($creds as $cred){
    echo $cred['tipo'];
    //if the next item has a 'tipo' key with a specific value
    if(current($creds['tipo'])!='4'){
        echo 'Total';
    }
}

but this is not working. How to fix it?

EDIT: based on the answers I will move the echo 'Total' stuff at the beginning of the next iteration instead of at the bottom of the current iteration. There are no other solutions using foreach as far as I see in the answers

Upvotes: 2

Views: 6007

Answers (4)

Ryan Vincent
Ryan Vincent

Reputation: 4513

The requirement is:

  • inside a foreach loop to look at the next value or key but not change the position of the current iterator pointer of the foreach loop.

Although it is more code, one way it to create a completely separate iterator on the same array.

This new iterator has to be kept in step with the foreach loop but that is quite simple to do.

The advantage is that you can manipulate any way you wish using next(), prev(), current() etc. and know that the foreach loop will not be affected.

For this example where the requirement is to test the next entry ahead of th current one. It is worthwhile just starting with the iterator pointing to the second entry and just advance each time.

Example, untested code...

$iter = new \ArrayIterator($cred)s; // mirror of the `foreach` loop 

iterator foreach($creds as $cred) {

    // get next key and value...
    $iter->next(); 
    $nextKey = $iter->key();
    $nextValue = $iter->current();

    echo $cred['tipo'];

    // if the next item has a 'tipo' key with a specific value
    if($nextValue['tipo']) != '4'){
        echo 'Total';
    }
}

Upvotes: 2

Mike Kor
Mike Kor

Reputation: 876

You can try using prev function after using next. It might be not be the best solution but it should work.

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

foreach ($values as $a) {
    print next($values);
    prev();
}

should output 2,3

EDIT

Actually next() is not affecting your loop key after execution and gives you right next value. It is also noticed in answer to link you provided. Also you can change iterations manually using custom iterator and prev function. http://php.net/manual/en/language.oop5.iterations.php

<?php
class MyIterator implements Iterator
{
    private $var = array();

    public function __construct($array)
    {
       if (is_array($array)) {
            $this->var = $array;
    }
}

public function rewind()
{
    reset($this->var);
}

public function current()
{
    $var = current($this->var);

    return $var;
}

public function key() 
{
    $var = key($this->var);
    return $var;
}

public function next() 
{
    $var = next($this->var);
    return $var;
}

public function prev()
{
    $var = prev($this->var);
    return $var;
}

public function valid()
{
    $key = key($this->var);
    $var = ($key !== NULL && $key !== FALSE);
    return $var;
}

}

$values = array(1,2,3);
$it = new MyIterator($values);

foreach ($it as $a => $b) {
   print 'next is '.$it->next();
   $it->prev();
}
?>

Upvotes: 0

Nick
Nick

Reputation: 2744

I'd check in each loop if the current item has your special key/value pair and then one more time at the end. This way you don't have to access the next item (and move the pointer forth and back). If it's more complicated than echo 'Total'; then you could wrap it into a function, to avoid code duplication in and after the foreach loop.

$creds = [
    ['tipo' => '1'],
    ['tipo' => '2'],
    ['tipo' => '3'],
    ['tipo' => '4'],
    ['tipo' => '5'],
];

foreach ($creds as $cred) {
    if ($cred['tipo'] == '4') {
        echo "Total\n";
    }
    echo $cred['tipo'] . "\n";
}
// If the very last row had the special key, print the sum one more time
if ($cred['tipo'] == '4') {
    echo "Total\n";
}


/* Output:
1
2
3
Total
4
5
*/

Edit:

I misinterpreted your requirement ("I want to place a total row after each item in the array if the next element in the array matches a specific condition"). If you want it the other way round, I'd suggest, to "buffer" the value of the current row in a variable $previous_row, until the foreach loop moves the pointer forward and you are able to access and check the value:

$creds = [
    ['tipo' => '1'],
    ['tipo' => '2'],
    ['tipo' => '3'],
    ['tipo' => '4'],
    ['tipo' => '5'],
];

$previous_row = '';
foreach ($creds as $cred) {
    echo $previous_row;
    if ($previous_row && $cred['tipo'] != '4') {
        echo "Total\n";
    }
    $previous_row = $cred['tipo'] . "\n";
}
// If the very last row had the special key, print the sum one more time
echo $previous_row;
if ($cred['tipo'] != '4') {
    echo "Total\n";
}


/* Output:
1
Total
2
Total
3
4
Total
5
Total
*/

Upvotes: 0

AkimBB
AkimBB

Reputation: 11

Try this code

$keys = array_keys($creds);

for($i = 0; $i < sizeof($keys); $i++)
{
    echo $creds[$keys[$i]] .' ';

    //$creds[$keys[$i+1]] - next item

    if($keys[$i+1] == 'tipo' && $creds[$keys[$i+1]] == 4 )
    {
        //
    }
}

Upvotes: 1

Related Questions