0

Ran into a little snag and wondering if there is a "best practices" way around it.

So I just learned that "A php foreach will execute on the entire array regardless. Test unsetting a value that is next in iteration. It will iterate on the offset, but the value will be null. – Kevin Peno Dec 22 '09 at 21:31" from How do you remove an array element in a foreach loop?

It's the first part of that that is messing with me. I'm iterating through an array with foreach. It's a search function so I'm removing the element I just searched for, so when the loop runs again its minus that element.

I do NOT want to reindex if at all possible, although if I have to I can.

Array
(
[0] => Array
    (
        [0] => a
        [1] => aa
        [2] => aaa
    )

[1] => Array
    (
        [0] => b
        [1] => bb
        [2] => bbb
    )

[2] => Array
    (
        [0] => c
        [1] => cc
        [2] => ccc
    )

[3] => Array
    (
        [0] => d
        [1] => dd
        [2] => ddd
    )

)

foreach($array as $key=>$value) {
   $searchresult[] = search function returns various other keys from array

   foreach($searchresult as $deletionid) {
      unset($array[$deletionid]);
   } 
}

So on the first iteration it uses $array[0] obviously but the $searchresults might return 4,5,6,7. So those keys are removed from $array.

Yet the foreach loop still iterates through those and gives me back a bunch of empty arrays.

I did read How does PHP 'foreach' actually work? and I get some of it.

Thanks

Community
  • 1
  • 1
TheEditor
  • 486
  • 1
  • 4
  • 18
  • 1
    You could just delete item you want while iterating with an if clause – Fabio May 18 '13 at 16:04
  • @Fabio How so? I just added an if(empty($array)) statement and that at least got rid of all the empty arrays. I guess I'm more interested in making it NOT iterate over those since they were unset. Or is that just a quirk of sorts. – TheEditor May 18 '13 at 16:10
  • What do you need to remove at first stage? – Fabio May 18 '13 at 16:12

2 Answers2

1

In my opinion, the best way to remove array elements based on indexes is to use the array_* set of functions, like array_diff and array_intersect (or array_diff_key and array_intersect_key in your situation).

$indexes_to_remove = array(2,3,4);
$indexes_to_remove = array_flip($indexes_to_remove);

$array = array_diff_key($array,$indexes_to_remove);
StampyCode
  • 7,218
  • 3
  • 28
  • 44
  • Tried that using array_diff_key and same thing. WHen the foreach loop starts there are an original 50 elements. No matter what I've tried it goes through all 50. Unless I break the loop on an if(empty($array)) condition. – TheEditor May 18 '13 at 16:25
  • If you use the array_diff then you don't need to loop through the array - loop through it once to build a list of indexes you wish to delete, then after you've left the loop, diff the data array against the elements you wish to remove. – StampyCode May 18 '13 at 16:36
  • I have to loop through, that's how the search runs. I get your point but that doesn't work in this scenario. I need to continue looping through the array until it's exhausted, which it does now, albeit a bit messy. – TheEditor May 18 '13 at 16:54
1

If the array is guaranteed to be exhausted at some point, you can use this:

while (true) {
    $searchresult[] = search function returns various other keys from array

    foreach($searchresult as $deletionid) {
        unset($array[$deletionid]);
    }
    if (count($array) === 0) {
        break;
    }
}

And yes I know while (true) is pretty evil, but I find in cases like these it does exactly what is needed. If you want to prevent it from infinite looping you could always add a variable, increment each iteration, and break when it reaches a high value that should never happen (like 10 * count($array))

rpkamp
  • 811
  • 4
  • 14
  • I'll give that a shot. Seems cleaner than if(!empty($array)) break. Pardon my ignorance but why is while ( true ) evil? Not that I've ever used it but just for learning sake. – TheEditor May 18 '13 at 21:59
  • Because if you never `break` the script will run forever (unless it hits a time limit of course) – rpkamp May 18 '13 at 22:01