How to delete object from array inside foreach loop?
Asked Answered
A

6

163

I iterate through an array of objects and want to delete one of the objects based on it's 'id' property, but my code doesn't work.

foreach($array as $element) {
    foreach($element as $key => $value) {
        if($key == 'id' && $value == 'searched_value'){
            //delete this particular object from the $array
            unset($element);//this doesn't work
            unset($array,$element);//neither does this
        } 
    }
}

Any suggestions. Thanks.

Anarchist answered 21/2, 2010 at 2:51 Comment(1)
possible duplicate of How do you remove an array element in a foreach loop?Swirsky
C
267
foreach($array as $elementKey => $element) {
    foreach($element as $valueKey => $value) {
        if($valueKey == 'id' && $value == 'searched_value'){
            //delete this particular object from the $array
            unset($array[$elementKey]);
        } 
    }
}
Cupriferous answered 21/2, 2010 at 2:56 Comment(7)
Is it safe to remove an element of an array within a foreach loop of the same array?Astrionics
@Oliver: usually it will generate unexpected behavior, but you can do it safely with foreach on php. Give a read here for a test: php.net/manual/en/control-structures.foreach.php#88578Signification
This is converting my array to object in CodeIgniter. Any suggestion?Possessed
@Possessed I know you posted this a long time ago, but it's because PHP uses associative arrays. So you have an index that's deleted: and it's getting encoded to JSON as an Object. Makes sense, since an associative array is a "dictionary." Might help someone who's coming along.Bushmaster
Do you really need to do the second for each ? can't you just query the desired 'id' property of the object? Why check all of the other props.Jehovah
@Jehovah no you could just do if(isset($element['id']) && $element['id'] == 'searched_value') { unset($array[$elementKey]); } I think at the time i just copied and modified his code to show him how to unset properly.Cupriferous
@pangon's reply could be misleading. His link shows foreach loop is unaffected by unset. If it is safe or not really depend on one's use case.Usufruct
F
5

Be careful with the main answer.

with

[['id'=>1,'cat'=>'vip']
,['id'=>2,'cat'=>'vip']
,['id'=>3,'cat'=>'normal']

and calling the function

foreach($array as $elementKey => $element) {
    foreach($element as $valueKey => $value) {
        if($valueKey == 'cat' && $value == 'vip'){
            //delete this particular object from the $array
            unset($array[$elementKey]);
        } 
    }
}

it returns

[2=>['id'=>3,'cat'=>'normal']

instead of

[0=>['id'=>3,'cat'=>'normal']

It is because unset does not re-index the array.

It reindexes. (if we need it)

$result=[];
foreach($array as $elementKey => $element) {
    foreach($element as $valueKey => $value) {
        $found=false;
        if($valueKey === 'cat' && $value === 'vip'){
            $found=true;
            $break;
        } 
        if(!$found) {
           $result[]=$element;
        }
    }
}
Fetus answered 18/4, 2020 at 11:50 Comment(1)
To reindex array You could use $array = array_values($array);Tsan
G
2

It looks like your syntax for unset is invalid, and the lack of reindexing might cause trouble in the future. See: the section on PHP arrays.

The correct syntax is shown above. Also keep in mind array-values for reindexing, so you don't ever index something you previously deleted.

Gyromagnetic answered 21/2, 2010 at 2:58 Comment(0)
C
1

This should do the trick.....

reset($array);
while (list($elementKey, $element) = each($array)) {
    while (list($key, $value2) = each($element)) {
        if($key == 'id' && $value == 'searched_value') {
            unset($array[$elementKey]);
        }
    }
}
Corlisscorly answered 7/2, 2013 at 18:54 Comment(0)
W
-1

You can also use references on foreach values:

foreach($array as $elementKey => &$element) {
    // $element is the same than &$array[$elementKey]
    if (isset($element['id']) and $element['id'] == 'searched_value') {
        unset($element);
    }
}
Watercress answered 9/6, 2015 at 12:17 Comment(2)
$element (used in and out of the foreach) is just a reference to each element in the array. unset($element) will just break reference, it does not destroy the referenced element from its array.Wardwarde
@Dev_NIX $element = null would NOT work, the length of $array remains the same, it would just contain nullsChromoprotein
L
-5

I'm not much of a php programmer, but I can say that in C# you cannot modify an array while iterating through it. You may want to try using your foreach loop to identify the index of the element, or elements to remove, then delete the elements after the loop.

Lulalulea answered 21/2, 2010 at 2:53 Comment(3)
While it is bad practice in most languages, arrays in PHP are basically associative arrays that can be iterated in order. Deleting an earlier element does not change the keys of elements that come after it.Trenttrento
Actually, it's allowed because the array that foreach uses internally is a copy of the original array. That way, modifying the original array is perfectly safe.Honest
Actually, it's allowed because php is screwy as all hell.Iyre

© 2022 - 2024 — McMap. All rights reserved.