Jump to content

foreach only analyses array at the start?


freelance84

Recommended Posts

$results = array('11','11','11');
$counter = 0;
foreach($results as $baseKey => $baseValue)
{
    print_r($results);
   //loop through all the $results counting the occurances of $baseValue
   foreach($results as $key => $valueToFind)
      {
         if($valueToFind == $baseValue)
            {
               unset($results[$key]);
               ++$counter;
            }
       }
}

 

results in: "Array ( [ 0 ] => 11 [ 1 ] => 11 ) Array ( )Array ( )"

 

Is this because the foreach function analyses the array and sets the number of times it should run the loop at the beginning and never analyses the array again?

 

The only way i could stop the loop from running if all values were unset was to add this at the end of the loop:

if(empty($results0to4))
    {
        break;
    }

Link to comment
Share on other sites

Is this because the foreach() function analyses the array and sets the number of times it should run the loop at the beginning and never analyses the array again?

Yes, the array the loop operates on is not the same array as what's available inside the loop.  I wrote an article on this subject a few years ago.

 

You're basically going to empty this array regardless of its contents.  What are you trying to do with this loop?  From what I can see, no matter what the initial settings of the array are, it will be empty when you're done.  Seems like a lost of wasted cycles to do that task.

 

Also, the output you claim you're getting isn't correct, there should be 3 items in the first array.

 

-Dan

Link to comment
Share on other sites

yea sorry that was a typo. There is three outputted from this example.

 

Yea, it is rather complex to explain fully, but essentailly there is three sets of results coming from different sources:

$resultsGr0

$resultsGr1

$resultsGr2

 

Some of the results are duplicated and spread across the different arrays. EG:

$resultsGr0 = array('11','11','123');

$resultsGr1 = array('234','11','75');

$resultsGr2 = array('123','18','66');

 

 

In the above example, the result '11' appears twice in $resultsGr0 and once in $resultsGr1.

 

The script i have written loops through the first array counting the number of occurrences of the foreach value in its own array.

It then counts how many times the value appears in each of the other arrays, and every time it finds a match, it removes the said value so as not to count it again later.

After reaching the end it then decides where to place the 'value'.

 

There is then a subsequent script which does a similar looping process through the latter two arrays (as the first array is now empty), and it decides where to place the values accordingly.

 

Then finally there is a foreach loop on the last array (although it may now be empty also)

The arrays above in reality are actually not as simple as i have made out, this was just to illustrate my question.

However, everything works like a charm when I add the break; into the end of each of the foreach loops.

 

I was just wondering how the foreach function actually worked. I will have a read of your article ManiacDan, thanks :)

Link to comment
Share on other sites

 

(after reading the article from ManiacDan)

 

If the foreach array places a copy into the servers memory at the start and then loops through accordingly, if the array is big then is foreach the wrong tool to use? foreach is very hand for being lazy, but if it dumps excess info into memory would it be better to be using a for loop and just use the value of $i as the key?

 

For example, which would be more efficient:

$words = array( a 4000 part array );
$count = count($words);

//loop1
foreach($words as $key = > $value)
{
   echo $key.' - '.$value.' <br/>';
}

//loop2
for($i = 0 ; $i < $count ; ++$i)
  {
    echo $i.' - '.$words[$i].'<br/>';
  }

//loop3 (i'm guessing this will be less efficient than loop2 as it has to keep counting the array each time
for($i = 0 ; $i < count($words) ; ++$i)
  {
    echo $i.' - '.$words[$i].'<br/>';
  }

Link to comment
Share on other sites

<?php
$arr = range(0,4000);
$count = count($arr);
//loop1
$start = microtime(true);

foreach($arr as $key => $value) {
$key . $value;
}
$end = microtime(true);
echo 'foreach: ' . number_format(($end - $start),5) . ' seconds!<br />';
//loop2
$start = microtime(true);
for($i = 0 ; $i < $count ; ++$i)
  {
    $arr[$i];
  }
$end = microtime(true);

echo 'for: ' . number_format(($end - $start),5) . ' seconds!<br />';
?>

results

foreach: 0.00312 seconds!
for: 0.00065 seconds!

 

Indeed, for is faster!

Link to comment
Share on other sites

Told you ;-)

 

Foreach is appropriate if you don't know the keys in advance, though you could still do:

$keys  = array_keys($aHugeArray);
for ( $p = 0; $p < count($keys); $p++ ) {
  $theVal = $ahugeArray[$keys[$p]];
}

As for your actual problem, if the example arrays aren't too complex you might be able to solve this entirely using array_merge and array_unique.  Maybe.

 

-Dan

Link to comment
Share on other sites

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.