How do you remove an array element in a foreach loop?
Asked Answered
D

6

157

I want to loop through an array with foreach to check if a value exists. If the value does exist, I want to delete the element which contains it.

I have the following code:

foreach($display_related_tags as $tag_name) {
    if($tag_name == $found_tag['name']) {
        // Delete element
    }
}

I don't know how to delete the element once the value is found. How do I delete it?

I have to use foreach for this problem. There are probably alternatives to foreach, and you are welcome to share them.

Due answered 22/12, 2009 at 21:22 Comment(1)
This question is missing its minimal reproducible example. It does not make a great canonical reference and answerers are afforded the freedom to stretch the interpretation of the input data to diversify recommended solutions -- not great for the researcher experience.Teamster
S
258

If you also get the key, you can delete that item like this:

foreach ($display_related_tags as $key => $tag_name) {
    if($tag_name == $found_tag['name']) {
        unset($display_related_tags[$key]);
    }
}
Sector answered 22/12, 2009 at 21:25 Comment(6)
Some additional info about optimizing by using $key => &$tag_name https://mcmap.net/q/41191/-unsetting-array-values-in-a-foreach-loop-duplicateFungus
Note that indexed arrays with items unset may be represented as objects instead of arrays after a json_encode(). You can solve this with $display_related_tags = array_values ($display_related_tags); after the foreach loop.Chophouse
Note that's the trick here is to add a value to the foreach loop ;-)Kazim
Please see @Neils answer. You will encounter unexpected bugs, especially if you work with Array of stdClasses. Do you like unexpected behavior? Me not.Ferryman
@Ferryman Neils answer is not helping. Snippet $projects = array_filter($projects, function ($project) { return count($project->roles) > 0; }); it converts result into object.Nam
Important If you are interested in keeping the array as ordered array, you need to call display_related_tags = array_values(display_related_tags); after it.Francoisefrancolin
S
48

A better solution is to use the array_filter function:

$display_related_tags =
    array_filter($display_related_tags, function($e) use($found_tag){
        return $e != $found_tag['name'];
    });

As the php documentation reads:

As foreach relies on the internal array pointer in PHP 5, changing it within the loop may lead to unexpected behavior.

In PHP 7, foreach does not use the internal array pointer.

Sesqui answered 9/8, 2016 at 11:32 Comment(5)
Note that the 3rd parameter should be ARRAY_FILTER_USE_KEY in order to pass the key as $e here.Heaven
@Heaven OK why does that matter here?Voiceless
@Voiceless From the documentation (php.net/manual/en/function.array-filter.php): ARRAY_FILTER_USE_KEY - pass key as the only argument to callback instead of the value ARRAY_FILTER_USE_BOTH - pass both value and key as arguments to callback instead of the value Default is 0 which will pass value as the only argument to callback instead. That said, reading the answer again in this case of course it would not matter as you claim.Heaven
Important If you are interested in keeping the array as ordered array, you need to call display_related_tags = array_values(display_related_tags); after it.Francoisefrancolin
So, can we now say that it is safe, in PHP 7, to directly unset the item from the array? It definitely seems much leaner than using the array_filter, at least from the coder's perspective (I'm not sure about the actual implementation in the background).Gibert
S
12
foreach($display_related_tags as $key => $tag_name)
{
    if($tag_name == $found_tag['name'])
        unset($display_related_tags[$key];
}
Streaming answered 22/12, 2009 at 21:25 Comment(1)
'unlink' unlinks files, it has nothing to do with variables or, more specifically, arrays. Perhaps you mean 'unset'?Logogram
B
6

Instead of doing foreach() loop on the array, it would be faster to use array_search() to find the proper key. On small arrays, I would go with foreach for better readibility, but for bigger arrays, or often executed code, this should be a bit more optimal:

$result=array_search($unwantedValue,$array,true);
if($result !== false) {
  unset($array[$result]);   
}

The strict comparsion operator !== is needed, because array_search() can return 0 as the index of the $unwantedValue.

Also, the above example will remove just the first value $unwantedValue, if the $unwantedValue can occur more then once in the $array, You should use array_keys(), to find all of them:

$result=array_keys($array,$unwantedValue,true)
foreach($result as $key) {
  unset($array[$key]);
}

Check http://php.net/manual/en/function.array-search.php for more information.

Byrnes answered 22/12, 2009 at 22:17 Comment(0)
V
0

if you have scenario in which you have to remove more then one values from the foreach array in this case you have to pass value by reference in for each: I try to explain this scenario:

foreach ($manSkuQty as $man_sku => &$man_qty) {

               foreach ($manufacturerSkus as $key1 => $val1) {

  // some processing here and unset first loops entries                     
 //  here dont include again for next iterations
                           if(some condition)
                            unset($manSkuQty[$key1]);

                        }
               }
}

in second loop you want to unset first loops entries dont come again in the iteration for performance purpose or else then unset from memory as well because in memory they present and will come in iterations.

Vinnievinnitsa answered 10/12, 2015 at 19:24 Comment(0)
V
0

There are already answers which are giving light on how to unset. Rather than repeating code in all your classes make function like below and use it in code whenever required. In business logic, sometimes you don't want to expose some properties. Please see below one liner call to remove

public static function removeKeysFromAssociativeArray($associativeArray, $keysToUnset)
{
    if (empty($associativeArray) || empty($keysToUnset))
        return array();

    foreach ($associativeArray as $key => $arr) {
        if (!is_array($arr)) {
            continue;
        }

        foreach ($keysToUnset as $keyToUnset) {
            if (array_key_exists($keyToUnset, $arr)) {
                unset($arr[$keyToUnset]);
            }
        }
        $associativeArray[$key] = $arr;
    }
    return $associativeArray;
}

Call like:

removeKeysFromAssociativeArray($arrValues, $keysToRemove);
Vaal answered 26/12, 2017 at 12:57 Comment(1)
I never call empty() on variables that are guaranteed to be declared.Teamster

© 2022 - 2024 — McMap. All rights reserved.