Continuously looping through an array - php

I'm trying to work out how to continuously loop through an array, but apparently using foreach doesn't work as it works on a copy of the array or something along those lines.
I tried:
$amount = count($stuff);
$last_key = $amount - 1;
foreach ($stuff as $key => $val) {
// Do stuff
if ($key == $last_key) {
// Reset array cursor so we can loop through it again...
reset($stuff);
}
}
But obviously that didn't work. What are my choices here?

An easy way is to combine an ArrayIterator with an InfiniteIterator.
$infinite = new InfiniteIterator(new ArrayIterator($array));
foreach ($infinite as $key => $val) {
// ...
}

You can accomplish this with a while loop:
while (list($key, $value) = each($stuff)) {
// code
if ($key == $last_key) {
reset($stuff);
}
}

This loop will never stop:
while(true) {
// do something
}
If necessary, you can break your loop like this:
while(true) {
// do something
if($arbitraryBreakCondition === true) {
break;
}
}

Here's one using reset() and next():
$total_count = 12;
$items = array(1, 2, 3, 4);
$value = reset($items);
echo $value;
for ($j = 1; $j < $total_count; $j++) {
$value = ($next = next($items)) ? $next : reset($items);
echo ", $value";
};
Output:
1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4
I was rather surprised to find no such native function. This is a building block for a Cartesian product.

You could use a for loop and just set a condition that's always going to be true - for example:
$amount = count($stuff);
$last_key = $amount - 1;
for($key=0;1;$key++)
{
// Do stuff
echo $stuff[$key];
if ($key == $last_key) {
// Reset array cursor so we can loop through it again...
$key= -1;
}
}
Obviously, as other's have pointed out - make sure you've got something to stop the looping before you run that!

Using a function and return false in a while loop:
function stuff($stuff){
$amount = count($stuff);
$last_key = $amount - 1;
foreach ($stuff as $key => $val) {
// Do stuff
if ($key == $last_key) {
// Reset array cursor so we can loop through it again...
return false;
}
}
}
while(stuff($stuff)===FALSE){
//say hello
}

Related

How to Count Skipped Items in PHP array

lets suppose that I have an Array;
$array = [1, 2, "Mohcin", "Mohammed", 3,];
I can Access this array and skip the items "Mohcin" and "Mohammed" inside the iteration using for or foreach loop and continue.. but my question how I can count the number of items that I skipped inside the loop? and that is "TWO" in this case.
Thanks in advance
$array = [1, 2, "Mohcin", "Mohammed", 3,];
$skipped = 0;
foreach ($array as $element) {
if ($someCondition) {
// Remove the element
$skipped++;
}
}
// You access $skipped here
You can do it even without a foreach loop.
$array = [1, 2, "Mohcin", "Mohammed", 3,];
$skip = ["Mohcin", "Mohammed"];
$diff = array_diff($array, $skip);
$skipCount = count($array) - count($diff);
echo $skipCount; // prints 2
But if you want with foreach for the reason of more complex logic, do like this
$skipCount = 0;
foreach($array as $value) {
if($value === "Mohcin" || $value === "Mohammed") {
$skipCount++;
continue;
}
// Do anything else when not skipped
}
echo $skipCount; // prints 2
You need to create variable that keeps count of skips every time you skip value.
$skips = 0;
for($counter = 0; $counter < count($array); $counter++) {
if(skip) {
$skips++;
continue;
}
}

PHP: how to do foreach and start from sixth element of collection?

is it possible to start a foreach loop from specific element [sixth element]?
im using this code:
<?php
$num=1;
foreach($temp_row as $key => $value) {
echo $num;
$num++;
}
?>
thanks :)
You can use for example array_slice()
$num = 5; //it will start from sixth element
foreach(array_slice($temp_row, $num) as $key => $value) {
echo $key.'=>'.$value.'<br>';
}
Not directly with a foreach(). The clue is in the each part of the name. It loops through all elements.
So how can we achieve it?
You could always just have an if() clause inside the loop that checks the key value before doing the rest of the work.
But if that's not workable for you, for whatever reason, I'd suggest using a FilterIterator to achieve this.
The FilterIterator is a standard PHP class which you can extend to create your own filters. The iterator can then be looped using a standard foreach() loop, picking up only the records that are accepted by the filter.
There are some examples on the manual page linked above that will help, but here's a quick example I've thrown together for you:
class SkipTopFilter extends FilterIterator {
private $filterNum = 0;
public function __construct(array $array, $filter) {
parent::__construct(new ArrayIterator($array));
$this->filterNum = $filter;
}
public function accept() {
return ($this->getInnerIterator()->key() >= $this->filterNum);
}
}
$myArray = array(13,6,8,3,22,88,12,656,78,188,99);
foreach(new SkipTopFilter($myArray, 6) as $key=>$value) {
//loop through all records except top six.
print "rec: $key => $value<br />";
}
Tested; outputs:
rec: 6 => 12
rec: 7 => 656
rec: 8 => 78
rec: 9 => 188
rec: 10 => 99
you could skip if counter is not 6th element...
<?php
$num=0;
foreach($temp_row as $key => $value) {
if( ++$num < 6 )
{
continue;
}
echo $num;
}
?>
Or with a for loop
$num = 1;
for($i=5; $i<= count($temp_row), $i++) {
echo $num;
$num++;
}
try this code:
$new_temp_row = array_slice($temp_row, 5);
foreach($new_temp_row as $key => $value) {
echo $value;
}
You may create new array with needed data part of origin array and work with it:
$process = array_slice ($temp_row, 5);
foreach($process as $key => $value) {
//TODO Your logic
}
Or you may skipp first siel elments:
<?php
$num=1;
foreach($temp_row as $key => $value) {
if ($num < 6) {
$num++;
continue;
}
//TODO Your logic
}
?>
I suggest you use a for look instead of a for each. You can then access both the key and value that are at i position inside your loop.
<?php
$num = 1;
$keys = array_keys( $temp_row );
for( $i = 5; $i < count( $temp_row ); $i++ ) {
$key = $keys[$i];
$val = $temp_row[$i];
echo $i;
}
?>
$i = 1;
foreach ($temp_row as $key => $value) {
if (($num = $i++) < 6) continue;
// Do something
}
Or
for ($i = 0; $i < 5; $i++) next($temp_row);
while(list($key, $value) = each($temp_row)) {
// Do something
}

print all arrary values except first value - php

I have an array of numbers. I can print all values using for each command in php. But what I want is, I don't want to print first value (ie, array[0]) and want to print all other values.
foreach($array as $k=>$val){
if($k){echo $val;}
}
for brevity, i did only exactly what was asked. The first index has a value of 0 which is falsy, so the value won't get echoed when tested in the if condition.
$cloneArray = $array;
array_shift($cloneArray); // will remove the first element of array
foreach($cloneArray as $key => $value){
echo $key." = ".$value;
}
this will also work if your array is in format of
array('key1' => 'value1', 'key2'=> 'value2', ...)
There are dozens..thousands of simple ways to do this. I'm going to list six:
$array = array(5, 6, 7, 8, 9);
foreach ($array as $index => $elem) {
if ($index == 0) {
continue;
}
echo $elem;
}
foreach($array as $index => $elem) {
if ($index != 0) {
echo $elem;
}
}
for ($x = 1; $x < count($array); $x++) {
echo $array[$x];
}
$keep = array_shift($array);
foreach ($array as $index => $elem) {
echo $elem;
}
array_unshift($array, $keep);
foreach (array_diff($array, array($array[0])) as $elem) {
echo $elem;
}
function print_not_zero($elem, $index) {
if ($index) {
echo $elem;
}
}
array_walk($array, 'print_not_zero');
I don't want to insult you, but as a developer you should think more critically for a moment and take the time to visualize the problem. Otherwise you might waste too much time on stackoverflow.
$i = 0
foreach($array as $single)
{
if ($i > 0)
echo $single;
$i++;
}
Although, unless you're using an associative array, a for cycle would be better perhaps.
$i=array(0,1,2,3);
foreach($i as $key=>$value)
{
if($key!='0')
echo $value;
}

how to write function Max($array) which returns the maximum value contained in $array or some array nested within $array

Eg:
$array= array(array(141,151,161),2,3,array(101,202,array(303,606)));
output :606
What you need is to recursively go through your array ; which means the max function, which is not recursive, will not be "enough".
But, if you take a look at the users's notes on the manual page of max, you'll find this note from tim, who proposes this recursive function (quoting) :
function multimax( $array ) {
// use foreach to iterate over our input array.
foreach( $array as $value ) {
// check if $value is an array...
if( is_array($value) ) {
// ... $value is an array so recursively pass it into multimax() to
// determine it's highest value.
$subvalue = multimax($value);
// if the returned $subvalue is greater than our current highest value,
// set it as our $return value.
if( $subvalue > $return ) {
$return = $subvalue;
}
} elseif($value > $return) {
// ... $value is not an array so set the return variable if it's greater
// than our highest value so far.
$return = $value;
}
}
// return (what should be) the highest value from any dimension.
return $return;
}
Using it on your array :
$arr= array(array(141,151,161),2,3,array(101,202,array(303,404)));
$max = multimax($arr);
var_dump($max);
Gives :
int 404
Of course, this will require a bit more testing -- but it should at least be a start.
(Going through the users' notes on manual pages is always a good idea : if you're having a problem, chances are someone else has already had that problem ;-) )
Same idea as Pascal's solution, only shorter thanks to the Standard PHP Library
$arr= array(array(141,151,161),2,3,array(101,202,array(303,404)));
echo rmax($arr);
function rmax(array $arr) {
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr));
// initialize $max
$it->next(); $max = $it->current();
// "iterate" over all values
foreach($it as $v) {
if ( $v > $max ) {
$max = $v;
}
}
return $max;
}
http://www.java2s.com/Code/Php/Data-Structure/FindtheMaximumValueinaMultidimensionalArray.htm
function recursive_array_max($a) {
foreach ($a as $value) {
if (is_array($value)) {
$value = recursive_array_max($value);
}
if (!(isset($max))) {
$max = $value;
} else {
$max = $value > $max ? $value : $max;
}
}
return $max;
}
$dimensional = array(
7,
array(3, 5),
array(5, 4, 7, array(3, 4, 6), 6),
14,
2,
array(5, 4, 3)
);
$max = recursive_array_max($dimensional);
$arr = array(array(141,151,161), 2, 3, array(101, 202, array(303,404)));
$callback = function ($value, $key) use (&$maximo) {
if( $value > $maximo){
$maximo = $value;
}
};
array_walk_recursive($arr, $callback);
echo '<pre>'; print_r($maximo);``
A more elegant solution:
function MaxArray($arr)
{
function findMax($currentValue, $currentKey)
{
global $maxValue;
$maxValue = ($currentValue > $maxValue ? $currentValue : $maxValue);
}
array_walk_recursive($arr, 'findMax');
return $GLOBALS['maxValue'];
}
It's very simple
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr));
$max = max(iterator_to_array($iterator, false));
Finding the max avoiding too much recursion :
function array_max(array $array) {
$context = func_get_args();
$max = -INF;
while (!empty($context)) {
$array = array_pop($context);
while (!empty($array)) {
$value = array_pop($array);
if (is_array($value)) {
array_push($context, $value);
}
elseif ($max < $value) {
$max = $value;
}
}
}
return $max;
}
A more general method avoiding too much recursion :
function array_reduce_recursive($default, array $array, $callback = null) {
$context = func_get_args();
$count = func_num_args();
if (is_callable(func_get_arg($count - 1))) {
$callback = array_pop($context);
}
else {
$callback = create_function('$x, $y', 'return $x < $y ? $y : $x;');
}
$reduced = array_shift($context);
while (!empty($context)) {
$array = array_pop($context);
while (!empty($array)) {
$value = array_pop($array);
if (is_array($value)) {
array_push($context, $value);
}
else {
$reduced = $callback($reduced, $value);
}
}
}
return $reduced;
}
function array_max_recursive() {
$args = func_get_args();
$callback = create_function('$x, $y', 'return $x < $y ? $y : $x;');
return array_reduce_recursive(-INF, $args, $callback);
}
By this way you can specify the callback method if you are looking for something else than the biggest number. Also this method takes several arrays.
The end way is less efficient of course.
With this you have a full compatibility with lot of PHP version.
function MaxArray($arr) {
$maximum = 0;
foreach ($arr as $value) {
if (is_array($value)) {
//print_r($value);
$tmaximum = MaxArray($value);
if($tmaximum > $maximum){
$maximum = $tmaximum;
}
}
else
{
//echo $value.'\n';
if($value > $maximum){
$maximum = $value;
}
}
}
return $maximum;
}

PHP: how to iterate through an array, and resume where you left off?

Here's my array:
$array = array(1,2,3,4,5,6,7,8,9,10);
I want to iterate through the array 5 times, do something else, then resume iteration where I left off.
foreach ($array as $value) {
//do something until key 5
}
//do something else now
//resume...
foreach ($array as $value) {
//key should start at 6
}
How can I do this? Is there a way to achieve this with a foreach loop?
Update: I realized it would be silly to repeat the same code twice. The reason I was asking this is because I'm using a foreach loop to display table rows. I wanted to display the first five and hide the rest. So this is what I ended up with:
<?php
$counter = 1;
foreach ($array as $object): ?>
<?php if ($counter > 5): ?>
<tr style="display: none;">
<?php else: ?>
<tr>
<?php endif; ?>
<td><?php echo $object->name; ?></td>
</tr>
<?php $counter++; ?>
<?php endforeach; ?>
You need to use PHP's internal array pointer.
Something like:
$arr = range(0, 9);
for($i = 0; $i < 5; $i++) {
print current($arr);
next($arr);
}
//the pointer should be half way though the array here
something like this:
$counter = 0;
foreach ($array as $value)
{
if($counter == 5)
{
do something random;
$counter++;
continue;
}
//do something until key 5
$counter++;
}
Just curious, but wouldn't calling a function in the array to do what you need done achieve the same result?
Use two arrays:
$first_five = array_slice($array, 0, 5);
$remainder = array_slice($array, 5);
Is there a reason you need to do this with foreach, as opposed to just for?
you can use each() to resume iterating.
$a = array(1,2,3,4);
foreach ($a as $v) {
if ($v == 2) break;
}
while (list($k, $v) = each($a)) {
echo "$k = $v\n";
}
I think jspcal had the best answer so far. The only modification I made to his code was to use a do-while loop instead, so it would not skip the element where first loop breaks.
$arr = array(1,2,3,4);
// Prints 1 2
foreach($arr as $v)
{
if ($v == 3)
{
break;
}
echo "$v ";
}
// Prints 3 4
do
{
echo "$v ";
}
while( list($k, $v) = each($arr) );
(For the problem as stated I wouldn't recommend it but:) You can also use the NoRewindIterator.
$array = array(1,2,3,4,5,6,7,8,9,10);
$it = new NoRewindIterator(new ArrayIterator($array));
foreach($it as $x) {
echo $x;
if ($x > 4) {
break;
}
}
// $it->next();
echo 'taadaa';
foreach($it as $x) {
echo $x;
}
prints 12345taadaa5678910.
(Note the duplication of the element 5. Uncomment the $it->next() line to avoid that).
It's a little kloodgy, but it should work:
foreach($array as $key => $value)
{
$lastkey = $key;
// do things
if($key == 5) break;
}
// do other things
foreach($array as $key => $value)
{
if($key <= $lastkey) continue;
// do yet more things
}

Categories