#1
  1. A Change of Season
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2004
    Location
    Next Door
    Posts
    2,689
    Rep Power
    171

    UNSET array element!


    Hi;

    Why does the code below UNSET [0] (the first element)? It should leave it alone as $var['ALLOTMENTS_STATS'] = b,b
    PHP Code:
    foreach($groupedData as $val=>$row)
        {
            foreach(
    $row as $var)
                {
                    if(
    strpos($var['ALLOTMENTS_STATS'],'n') !== false
                        {
                            unset(
    $groupedData[$val]);
                        }
                }
        } 
    These are the removed elements:
    Code:
    Array([0] => Array (
    [TOTAL] => 248.00
    [ALLOTMENTS_STATS] => b,b
    [ALLOTMENTS_NOR] => 1,1)
    
    [1] => Array(
    [TOTAL] => 228.00
    [ALLOTMENTS_STATS] => n,n
    [ALLOTMENTS_NOR] => 1,1)
    
    )
    Thanks
  2. #2
  3. Jealous Moderator
    Devshed Supreme Being (6500+ posts)

    Join Date
    Mar 2007
    Location
    Washington, USA
    Posts
    14,302
    Rep Power
    9400
    It is not safe to unlink() something in an array you are foreaching over.

    Build an array of keys to remove, then use a separate loop to actually remove.
  4. #3
  5. A Change of Season
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2004
    Location
    Next Door
    Posts
    2,689
    Rep Power
    171
    Originally Posted by requinix
    It is not safe to unlink() something in an array you are foreaching over.

    Build an array of keys to remove, then use a separate loop to actually remove.
    Unlink? I am using unset. Please explain if you can.
    Thank you
  6. #4
  7. Jealous Moderator
    Devshed Supreme Being (6500+ posts)

    Join Date
    Mar 2007
    Location
    Washington, USA
    Posts
    14,302
    Rep Power
    9400
    Er, yeah, unset(). Been typing "unlink" a lot today

    foreach doesn't work on a copy of the array, like most things do. It modifies internal information about the array - a pointer to the current item, to be specific. When you delete things from the array that pointer can get messed up.

    That explanation isn't quite accurate but whatever, it might not actually be the problem.
    It's hard to tell from your post: what's the value of $groupedData before this code executes?
  8. #5
  9. A Change of Season
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2004
    Location
    Next Door
    Posts
    2,689
    Rep Power
    171
    Originally Posted by requinix
    Er, yeah, unset(). Been typing "unlink" a lot today

    foreach doesn't work on a copy of the array, like most things do. It modifies internal information about the array - a pointer to the current item, to be specific. When you delete things from the array that pointer can get messed up.

    That explanation isn't quite accurate but whatever, it might not actually be the problem.
    It's hard to tell from your post: what's the value of $groupedData before this code executes?
    This is the whole story:
    PHP Code:
    $q_get_package"A huge SQL";
    $results DB::Load()->Execute($q_get_package)->returnArray();    
    $groupedData=array();
    foreach(
    $results as $item)
        {
            if(!
    array_key_exists($item['RID'],$groupedData))
                {
                    
    $groupedData[$item['RID']] = array();
                }
            
    $groupedData[$item['RID']][] = $item;     
        } 
  10. #6
  11. No Profile Picture
    Lost in code
    Devshed Supreme Being (6500+ posts)

    Join Date
    Dec 2004
    Posts
    8,316
    Rep Power
    7171
    requinix means an actual example of the $groupedData array. Chances are your 'b,b' row is in the same $groupedData element as some other row that contains an 'n', and is being removed for that reason.

    foreach actually does operate on a copy of the array, so unlink should work. I'm not sure if this has always been true, but it can be easily demonstrated by the fact that the following does not cause an infinite loop:
    PHP Code:
    $a = [1,2,3];
    foreach(
    $a as $k => &$vreset($a); 
    The manual page for foreach does actually imply that the above snippet would cause an infinite loop (and that unlink would not work inside a foreach), but the manual page is wrong in any sense that matters (there are technical reasons why you could consider the statements it makes to be correct, but that they are so misleading makes them wrong regardless).


    edit: note that while this is true of arrays, I think it might not be true of iterating over things that are not arrays.
    Last edited by E-Oreo; June 19th, 2013 at 01:41 AM.
    PHP FAQ

    Originally Posted by Spad
    Ah USB, the only rectangular connector where you have to make 3 attempts before you get it the right way around
  12. #7
  13. Jealous Moderator
    Devshed Supreme Being (6500+ posts)

    Join Date
    Mar 2007
    Location
    Washington, USA
    Posts
    14,302
    Rep Power
    9400
    Hmm, maybe something's changed. I'm pretty sure it used to be that unset()ing inside the loop would do funny things like skip items
    PHP Code:
    $array range(110);
    foreach (
    $array as $key => $value) {
        echo 
    $value;
        unset(
    $array[$key]);

    Code:
    1 3 5 7 9
    but I can't reproduce it in 5.3.

IMN logo majestic logo threadwatch logo seochat tools logo