Jump to content

Recommended Posts

Is there any way to reset a foreach loop, or do I have to use a for loop instead?

 

I'm trying to get this to print "1 5 10 1 5 10 "

 

<?php
$arrA = array(1, 5, 10);
$firstRun = true;
foreach ($arrA as $value) {
    echo $value.' ';
    if ( ($firstRun == true) && ($value == 10) ) {
        $firstRun = false;
        reset($arrA);
    }
}
?>

Link to comment
https://forums.phpfreaks.com/topic/135452-solved-reset-a-foreach-loop/
Share on other sites

I do not think it is possible, but you could make your own function that is recursive...

 

<?php
$arrA = array(1, 5, 10);
$firstRun = true;
foreachTwice($arrA, true);

function foreachTwice($array, $continue) {
foreach ($array as $value) {
	echo $value.' ';
	if ( ($continue) && ($value == 10) ) {
		foreachTwice($array, false);
	}
}
}

?>

 

That can also be manipulated to go so much further to, as it is it will only run twice.

This is already going to be used in the context of a recursive function. It's not the output that I'm looking for, it's the sequence. Maybe this will better illustrate it:

 

Desired output is "1 5 1 5 10 "

 

<?php
$arrA = array(1, 5, 10);
$firstRun = true;
foreach ($arrA as $value) {
    echo $value.' ';
    if ( ($firstRun == true) && ($value == 5) ) {
        $firstRun = false;
        reset($arrA);
    }
}
?>

edit: removed below and re-thinking it.

 

<?php
$arrA = array(1, 5, 10);
$firstRun = true;
foreachLoop($arrA, 5); 

function foreachLoop($array, $endAt=false) {
foreach ($array as $value) {
	echo $value.' ';
	if (!$endAt)
		continue; // if endat is false just continue and skip below

	if (($value == $endAt) ) {
		foreachLoop($array, false);
		break;
	}
}
}
?>

 

That would work, that way you give it a value and once it hits that it breaks out etc.

 

As for which is better, this or a for loop really it is your call. But foreach doesn't have a built in function to do that as far as I know.

edit: removed below and re-thinking it.

 

code

 

That would work, that way you give it a value and once it hits that it breaks out etc.

 

As for which is better, this or a for loop really it is your call. But foreach doesn't have a built in function to do that as far as I know.

 

I guess my example isn't a good enough parallel to my situation, as I have no idea how to implement your solution. What I'm ultimately trying to do is to flatten a multi-dimensional array, with elements of Glue inserted between the elements of a childless sub-array, and elements of Break inserted between the elements of a parent array. Since my current function iterates through the array passed to it only once, it will insert A between non-array elements even if an array element is present further down the line. If I run it on $arrA, defined as array(1, 2, array(3, 4), 5), I want the result equal array(1, B, 2, B, 3, G, 4, B, 5). In its present form, the result equals array(1, G, 2, G, 3, G, 4, B, 5), because it assumes that the top-level array is childless until it finds otherwise. Here's the code, with the faulty reset:

 

<?php
/////////////
// brackets are incorrect right now
/////////////
function flat_insert($source, $glue, $break) {
    if (!is_array($source)) {
        return null;
    }
    $stack1 = array(); //this will be returned
    $child = true;
    foreach ($source as $value) {
        if ((is_array($value)) && ($child == true)) { //if we find an array
            $child = false;
            reset($source); //re-start loop
            $stack1 = array(); //clear stack for restart
        }
        else if ((is_array($value)) && ($child == false)) { //if we already know we're in a parent, and we find a sub-array
            foreach (flat_insert($value, $glue, $break) as $v2) { //iterate through recursed sub-array
                $stack1[] = $v2;
            }
            unset($v2);
            if ($value != end($source)) { //only insert fill if we're not at the end
                $stack1[] = $break;
            }
        }
        else if ($child == false) { //parent array, current is not a sub-array
            $stack1[] = $value;
            if ($value != end($source)) {
                $stack1[] = $break;
            }
        else { //presume childless
            $stack1[] = $value;
            if ($value != end($source)) {
                $stack1[] = $glue;
            }
        }
    }
    unset($value);
    return $stack;
}
?>

Alright, I got it. The trick is to pass a new variable by reference into all extra elements, then change the value of the variable at the end of the function based on whether it's a parent or child. Here's the function and some sample outputs:

 

<?php
function flat_insert2($source, $glue, $break) {
    if (!is_array($source)) {
        return null;
    }
    $stack1 = array();
    $child = true;
    $insert = $glue;
    foreach ($source as $value) {
        if (is_array($value)) { //if we find a sub-array in current element
            $child = false;
            foreach (flat_insert2($value, $glue, $break) as $v2) { //iterate through recursed sub-array
                $stack1[] = $v2;
            }
            unset($v2);
        }
        else { //current element is not an array
            $stack1[] = $value;
        }
        $stack1[] = &$insert; //pass insert as reference
    }
    unset($value);
    array_pop($stack1); //remove trailing insert
    if ($child == false) {
        $insert = $break;
    }
    return $stack1;
}
?>

 

<?php
$arrF = array(8, 9);
$arrE = array(6, 7);
$arrD = array(4, 5);
$arrC = array($arrD, $arrE, $arrF, 10);
$arrB = array(2, 3, $arrC);
$arrA = array(1, $arrB, 11);
echo 'Array A: '.implode(flat_insert2($arrA, '-', ' ')).'<br />';
echo 'Array B: '.implode(flat_insert2($arrB, '-', ' ')).'<br />';
echo 'Array C: '.implode(flat_insert2($arrC, '-', ' ')).'<br />';
echo 'Array D: '.implode(flat_insert2($arrD, '-', ' ')).'<br />';
?>

Output:
Array A: 1 2 3 4-5 6-7 8-9 10 11
Array B: 2 3 4-5 6-7 8-9 10
Array C: 4-5 6-7 8-9 10
Array D: 4-5

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.