Stepping over an item in an array - php

I have an array such which lists a number of options for a menu and then in each of those options another array of suboptions.
In one display I want to check the key of one of the top options i.e 'useroptions' and if I find that, I want to skip over that whole subarray and move onto the next one. I'm having a problem at the moment though I have this code, but it shows the last suboption
if($item->key=='useroptions' {
$item = $item->children->last();
}
I would have thought something like
$item = $item->sibling->next();
but this isn't working.. Can anyone show me the correct way please.
Thanks
Wheelz

Check this example:
$arr = array(1, 2, 3, 4);
foreach ($arr as &$value) {
switch($value) {
case 3:
echo '<p>Skipped the number 3</p>';
break 1;
default:
break;
}
}
?>
Or this one:
foreach ( $array as $value ) {
if ( $value == 3 )
continue; # Skips
# Code goes here...
}

if($item->key != 'useroptions') {
// Do something using subarray
}

You can use the php function next() to advance to the next pointer in array.
next($array)
http://php.net/manual/en/function.next.php

if that if is inside a loop then do this it might help :
if($item->key=='useroptions') {
continue;
}

Related

Removing a certain number out of a session array in PHP

I have a button next to all my 'shop items' that can remove one of the shop item, however i need it to just remove one, and not rid the entire array of the number, i thought this was possible by using a break statement when i found the number i want to remove, but it removes all of the numbers.
if (isset($_GET['remove']) && isset($_SESSION['shopitems'])) {
if (in_array($_GET['remove'], $_SESSION['shopitems'])) {
for ($i = 0; $i < sizeof($_SESSION['shopitems']); $i++) {
if ($_SESSION['shopitems'][$i] == $_GET['remove']) {
$shopArray = $_SESSION['shopitems'];
if(sizeof($shopArray) == 1) {
$_SESSION['shopitems'] = null;
$_SESSION['added'] = null;
} else {
array_splice($shopArray, $i, $i);
$_SESSION['shopitems'] = $shopArray;
}
break;
}
}
}
}
Here i check if the URL contains the remove variable and the session is set, once i have done this, i check if the array contains the number that is put in the URL, if so i'll start a for loop and check if the key index of the session shop items is equal to the URL variable, if so i want to remove it, however if i use array_splice, suddenly they are all gone, is this because of the function i am using? Or is the break not executing correctly?
Why don't you try array_search() and unset()? It's easier, have a look at the code below and adapt it to your situation:
$array = [1, 5, 6, 12];
$wantToRemove = 5;
$key = array_search($wantToRemove, $array);
unset($array[$key]);
var_dump($array);
You can format your $_SESSION['shopitems'] like this :
$_SESSION['shopitems'] = array (
"item_id" => "item_info",
"item2_id" => "item2_info",
...
)
and do unset($_SESSION['shopitems'][$_GET['remove']]).
Your code could be :
if (isset($_GET['remove']) && isset($_SESSION['shopitems']))
if (isset($_SESSION['shopitems'][$_GET['remove']]))
unset($_SESSION['shopitems'][$_GET['remove']])

Iterating over one dimension of array until a value found

I have an array as follows
$array[$id][$iterator][test1][test2][a][b][c][d]
I would like to test for each $iterator for the first instance of test1=not null (if so use a, b, c d)
else use the first instance of test2=not null use (a, b, c, d)
else use "---"
I don't know how to get a loop to break on first instance of a finding test1 and test2 or if there is a better construct to use than a loop in this case?
To break an iteration or loop
Just tell it to take a break :)
foreach ($array as $item) {
if ($item == 'I the great overlord command you to stop iterating!') {
break;
}
}
If you wanna...
if you just want to know if a certain value is in your array, you can do it like this:
if (in_array('The value you are looking for', $thatArrayItShouldBeIn)) {
die("Its in! Its in! Yippie!");
}
From the comments
Tell me if I'm wrong, but from your comment I come to understand you want your iteration to break at a certain loop?
foreach ($array as $key => $item) {
// Keys start at 0, so the first item is 0
if ($key == 3) {
// We'll stop looping at the 4th iteration
break;
}
}
Taking yet another look
If you really have an array with alot of layers and you just want to check one value for each iteration you can just do:
foreach ($array[$id]['iterator'] as $item) {
if ($item['test1'] == true) {
// Do something
}
} }

how to get the index of an array using the value in php

<?php
$interests[50] = array('fav_beverages' => "beer");
?>
now i need the index (i.e. 50 or whatever the index may be) from the value beer.
I tried array_search(), array_flip(), in_array(), extract(), list() to get the answer.
please do let me know if I have missed out any tricks for the above functions or any other function I`ve not listed. Answers will be greatly appreciated.
thanks for the replies. But for my disappointment it is still not working. btw I have a large pool of data like "beer");
$interests[50] = array('fav_cuisine' => "arabic");
$interests[50] = array('fav_food' => "hummus"); ?> . my approach was to get the other data like "arablic" and "hummus" from the user input "beer". So my only connection is via the index[50].Do let me know if my approach is wrong and I can access the data through other means.My senior just informed me that I`m not supposed to use loop.
This should work in your case.
$interests[50] = array('fav_beverages' => "beer");
function multi_array_search($needle, $interests){
foreach($interests as $interest){
if (array_search($needle, $interest)){
return array_search($interest, $interests);
break;
}
}
}
echo multi_array_search("beer", $interests);
If your array contains multiple sub-arrays and you don't know which one contains the value beer, then you can simply loop through the arrays, and then through the sub-arrays, to search for the value, and then return the index if it is found:
$needle = 'beer';
foreach ($interests as $index => $arr) {
foreach ($arr as $value) {
if ($value == $needle) {
echo $index;
break;
}
}
}
Demo

Unsetting elements from array within foreach

I'm currently working on a generic form creation class and had an issue yesterday.
I made a snippet to reproduce the problem.
Essentially I want to delete elements that are grouped from the original elements array after the whole group has been drawn and I'm doing this while looping over the elements array.
The code snippet should cover the problem, am I missing something here? From my knowledge deleting an element while foreach is completely safe and legal since foreach internally only uses a copy that may be modified during the loop.
$ids = array('a' => array(), 'b' => array(), 'c' => array());
$groups['g1'] = array('a', 'c');
foreach($ids as $id => $element) {
//var_dump($ids);
$g_id = '';
// search the id in all groups
foreach($groups as $group_id => $group) {
if(in_array($id, $group)) {
$g_id = $group_id;
break;
}
}
// element is part of a group
if($g_id !== '') {
//echo $g_id;
// element a and c gets unset within loop and should not be in $ids anymore
foreach($groups[$g_id] as $field_id) {
unset($ids[$field_id]);
echo $field_id;
}
unset($groups[$g_id]);
} else {
if($id === 'a' || $id === 'c')
echo $id;
}
}
Element 'c' gets unset within the foreach(groups ..) loop but is afterwards again outputted in the else branch. Also when i var_dump($fields) at the beginning i always get 'a', 'b' and 'c' inside. I'm using PHP 5.4.7.
Thanks in advance
EDIT: i made a mistake in the sample code, its now updated. All comments about using the wrong index (it would have been 0,1 etc) were correct of course.
The values when using var_dump are unset now, but i still get into the else with 'c' one time.
EDIT2:
Im not done with the original code but after reading through the comments I currently came up with following solution to the posted code snippet above:
$ids=array("a"=>array(),"b"=>array(),"c"=>array(),"d"=>array(),"e"=>array());
$groups=array(array("a"),array("c", "e"));
array_walk($groups,function($v,$i)use(&$ids){
$in_both = array_intersect(array_keys($ids),$v);
//var_dump($in_both);
foreach($in_both as $b) {
unset($ids[$b]);
}
});
print_r($ids);
or
$ids=array("a"=>array(),"b"=>array(),"c"=>array(),"d"=>array(),"e"=>array());
$groups=array(array("a"),array("c"));
array_walk($ids,function($v,$i)use(&$ids, $groups){
$in_both = array();
foreach($groups as $g) {
if(in_array($i,$g)) {
$in_both = array_intersect(array_keys($ids),$g);
}
}
foreach($in_both as $b) {
unset($ids[$b]);
}
});
print_r($ids);
Using a foreach does not work for me in this case, because i need to change the $ids array while the loop is iterating over it.
In the very most basic situation a code something like this:
$ids = array('a', 'b');
while(count($ids)) {
array_pop($ids);
echo 'pop';
}
echo 'empty';
Allthough foreach can change the original values from the array it will not change the copy of the array used for the iteration as nl-x already stated.
Thanks to Passerby for the idea of using array_walk for this.
EDIT3:
Updated code snipped once more. The second snipped allthough behaves undefined as well. Deleting elements from an array while iterating over its seems to be a bad idea.
Chris, if I understand correctly, you don't expect 'C' to be outputted in the else branch?
But it should be outputted. Your logic is:
you do foreach ids and start with id 'a'.
then you clear ids a and c from ids and delete the group g1 that contained 'a'. During this step the deleted ids will be outputted, being a and c. (Clearing a and c from ids will have no impact on the foreach($ids as $id) as foreach will continue with the untouched copy even after ids array has been cleared.)
then you do id 'b': it is not found in any group. (actually, there isn't any group left by now anyway)
so for 'b' you enter the else branch. But the if() inside the else branch prevents output
then you do id 'c', which is also not found in any group, because you have already deleted group g1! There are no groups left, remember?
so for 'c' you also enter the else branch. And this time the if() inside the else branch allows the output! The output being just c
So the total output is indeed acc.
It is good to know that a foreach() that continues with a untouched copy even after its elements were cleared, is a specific PHP thing. Other language do no necessarily do the same.
Spent some time reading your code, and I guess your procedure is:
For every element in $ids, check if it exists in some sub-array in $groups;
If it exists, delete everything in $ids that also exists in this sub-array.
Following the above logic, I come up with this:
$ids=array("a","b","c","d","e");
$groups=array(array("a","c"),array("c","e"));
array_walk($groups,function($v,$i)use(&$ids){
$ids=array_diff($ids,$v);
});
print_r($ids);//debug
Live demo
I'm double checking now. But I think unsetting an array with foreach is not really safe.
What I usually would do is take a foreach, and start with the highest indexes and descrease the index along the way. for($i = count($arr)-1; $i >= 0; $i--) { unset($array[$i]); }
I'll edit this post in a few minutes.
edit: i was confused. The for with $i++ is indeed the culprit. foreach is safe (in php! not in all languages)
<?php
$arr = Array(1,2,3,4,5,6,7,8,9,10);
foreach ($arr as $key=>$val)
unset($arr[$key]);
echo implode(',',$arr); // returns nothing
$arr = Array(1,2,3,4,5,6,7,8,9,10);
for ($i=0; $i<count($arr); $i++)
unset($arr[$i]);
echo implode(',',$arr); // returns 6,7,8,9,10
$arr = Array(1,2,3,4,5,6,7,8,9,10);
for ($i=count($arr)-1; $i>=0; $i--)
unset($arr[$i]);
echo implode(',',$arr); // returns nothing
?>
$ids[$field_id] does not exist, you are using the value instead of the key.
You should simply unset using the right key :
if (in_array($field_id, $ids))
unset($ids[array_search($field_id, $ids)]);
If you want to remove the element from the array, shouldn't you 'splice' it out instead with array_splice?
From the PHP manual: http://php.net/manual/en/function.array-splice.php
Your foreach wont make any changes since a copy of array is used.. you will need to use pass by reference in order for this to work. one of the way is mentioned below
while(list($key,$value) = each($array)){
if(your reason to unset)
unset($array[$key]);
}
this will remove the element from the array.

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

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

Categories