How do you remove an array element in a foreach loop? - php

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.

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]);
}
}

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.

foreach($display_related_tags as $key => $tag_name)
{
if($tag_name == $found_tag['name'])
unset($display_related_tags[$key];
}

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.

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.

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);

Related

Is it safe to append to an array in a while loop?

There are numerous questions out there about the safety implications of manipulating an array when using foreach on it. I can't find any questions on doing this in a while loop, though.
So I wonder, is it safe to do this? Below is an example script in PHP and I'm not sure if this is alright.
while ($item = array_pop($array)) {
findMoreItems($item, $array);
}
function findMoreItems($item, &$array) {
// Returns null if no more items are found
$newItem = someFuncFromServer($item);
if ($newItem) {
array_push($array, $newItem);
}
}
By safe I mean: can I be sure that no items are skipped in the loop?
Your code is essentially equivalent to :
$item = array_pop($array);
while ($item) {
findMoreItems($item, $array);
$item = array_pop($array)
}
function findMoreItems($item, &$array) {
// Returns null if no more items are found
$newItem = someFuncFromServer($item);
if ($newItem) {
array_push($array, $newItem);
}
}
Now if you rewrite this in the above way it is obvious that the code will not do anything like copy references or array points or anything like that which is what foreach does. foreach does that because it relies on the internal array pointer which array_pop and array_push do not.

Remove session index php

New to php
I want to remove index with value from php session array. I'm using this code
$max=count($_SESSION['Item']);
for($i=0;$i<$max;$i++){
if(strpos($_SESSION['Item'][$i]['Name'],'Shipping')!== false)
{
unset($_SESSION['Item'][$i]);
break;
}
its working fine if value exists in last index of array. But if it exists in between. it doesn't work at all. Where am i going wrong?
Try to use array_splice, to remove items
array_splice($_SESSION['Item'], $i, 1);
I recommend using the foreach instead of for. This way your array keys can be more then only int. And is guaranteed to loop over all the array items
foreach($_SESSION['Item'] as $key => $value) {
if (strpos($value['Name'],'Shipping')!== false) {
unset($_SESSION['Item'][$key]);
}
}
As pointed out the break will stop the loop. So if you only want to remove a single entry, you should add the break
if(strpos($_SESSION['Item'][$i]['Name'],'Shipping')!== false)
{
unset($_SESSION['Item'][$i]);
}

Nested foreach loops, PHP, how do I manipulate the values?

foreach ($bing_array as $bing_array_val)
{
foreach ($final_array as $final_array_val)
{
if ($final_array_val["link"] == $bing_array_val["link"])
{
$final_array_val["rank"] += $bing_array_val["rank"];
}
}
}
The above code has two foreach loops, which are nested.
It should test every bing_array["link"] against every final_array["link"] and if they are the same, the final_array["rank"] value should be += bing_array["rank"] but when I echo final_array, the ["rank"] values are unchanged.
I assume this is a syntax problem, where am I going wrong?
Thanks
You need to use the reference syntax (& prefix):
foreach ($final_array as &$final_array_val)
{
}
unset($final_array_val);
Note that the unset is required to break the reference to the last value. Read more here.
Here is the actual code you need :
foreach ($bing_array as &$bing_array_val)
{
foreach ($final_array as &$final_array_val)
{
if ($final_array_val["link"] == $bing_array_val["link"])
{
$final_array_val["rank"] += $bing_array_val["rank"];
}
}
unset(&$final_array_val);
}
unset(&$bing_array_val);
In your initial code, each time you were looping on $final_array, it was creating a temporary value called $final_array_val containing the content. Then, you modified it, and then it was replaced for each occurence of the foreach.
By passing the variables by reference, instead of creating a new temporary variable in the foreach, you use the actual variable which will keep the modifications you have done to it.

push into array while it is being looped

Here's a snippet of my code. I understand that it is generally advised against to modify an array whilst it is being looped, however in this scenario I think it is the right thing to do and saves resources.
$levels = array($post);
foreach ($levels as $level) {
$next_sibling = get_next_sibling_page($level);
if ($next_sibling) {
$next_page = $next_sibling;
break 1;
} else if ($level->post_parent) {
array_push($levels, get_page($level->post_parent));
}
}
The idea is that the foreach would reiterate with the pushed value if ($level->post_parent), I can see that the if statement is resolving to true and the array is being pushed to however the foreach does not reiterate and only runs the one time.
Does anyone know how I can recursively continue my foreach until $level->post_parent resolves to false?
To modify array which is being used in foreach pass array by referance.
foreach (&$levels as $level) {
.....
}

Filtering an array in php, having both value- and key-related conditions

I'm trying to filter an array, in which the filter function is supposed to check for multiple conditions. For example, if element x starts with a capital letter, the filter function should return true. Except, if the element before element x satisfies certain other conditions, then element x should not stay in the array and the filter function should therefore return false.
Problem is that the callback function in array_filter only passes the element's value and not its key... doing some magic with array_search will probably work, but I was just wondering whether I'm looking in the wrong place for this specific issue?
Sounds like a case for a good old foreach loop:
foreach ($arr as $k => $v) {
// filter
if (!$valid)
unset($arr[$k]);
}
$newArray=array();
foreach($oldArray as $key=>$value){
if(stuff){
$newArray[$key]=$value;
}
}
or
foreach($array as $key=>$value){
if(stuff){
unset($array[$key]);
}
}
Did you use simple foreach?
$prev;
$first = true;
$result = array();
foreach ($array as $key => $value)
{
if ($first)
{
$first = false;
// Check first letter. If successful, add it to $result
$prev = $value;
continue; // with this we are ignoring the code below and starting next loop.
}
// check $prev's first letter. if successful, use continue; to start next loop.
// the below code will be ignored.
// check first letter... if successful, add it to $result
}

Categories