Reputation: 6673
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
Reputation: 4513
The requirement is:
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
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
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
*/
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
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