The problem I am facing is when I use one foreach inside another and the array of the first foreach has more than 1 entries. What I want to do is to exclude all entries of array 1 from array 2. I've been on almost all related posts, cannot solve it by myself, I need a little help if possible. Sorry for my bad English.
Example:
$choice
---> array with random number of entries each time (for this example 2)
Example:
/var/www/clients/client1/web1/web/images,/var/www/clients/client1/web1/web/tmp
$list
---> array of random number of entries each time (for this example 10000)
Example:
/var/www/clients/client1/web1/web/images,/var/www/clients/client1/web1/web/tmp,/var/www/clients/client1/web1/web/includes,/var/www/clients/client1/web1/web/libraries,......
$list
has always more entries than $choice
And I have this code here:
foreach ( $choice as $select )
{
foreach ( $list as $file )
{
if ( (strpos( $file, $select )) !== false )
{
// exclude this
}
else
{
// include this
}
}
}
What the above code will do (unfortunately) is:
Step 1. Will compare $select
entry-1 with all $file
entries.
Step 2. Will exclude $select
entry-1 from all $file
entries and will include the $select entry-2.
Step 3. Will compare $select
entry-2 with all $file
entries.
Step 4. Will exclude $select
entry-2 from all $file
entries and will include the $select entry-1.
Result: Nothing excluded.
Any help truly appreciated. I am on this for like a week, all I have tried is putting them inside out I am out of ideas. Thank you.
1 Answer 1
I believe you're trying to remove items that are in $list from $choice. (Or is it the other way around?) Have you tried the array_diff function? This will work if items in both array are equal. For example:
<?php
//Option 1: array_diff
$bigger = array("A", "B", "C", "D", "E", "F");
$smaller = array("A", "B");
$result = array_diff($bigger, $smaller);
print_r($result);
If you need to do additional processing on the removed items, you can try in_array, but this requires item equality (like above). For example:
//Option 2: in_array (only one foreach loop)
foreach ($smaller as $key => $item) {
if (in_array($item, $bigger)) {
//do something to "remove" it, for example:
unset($smaller[$key]);
unset($bigger[$key]);
//...
}
}
print_r($smaller);
print_r($bigger);
Lastly, if the items in both arrays are not guaranteed to be strictly equals, you could use a double foreach. You'll need to flag items in the inner loop and process them in the outer loop. For example:
//Option 3: double-foreach (items not strictly equals)
$choice = array(
"/var/www/clients/client1/web1/web/images",
"/var/www/clients/client1/web1/web/tmp"
);
$list = array(
"/var/www/clients/client1/web1/web/images",
"/var/www/clients/client1/web1/web/tmp",
"/var/www/clients/client1/web1/web/includes",
"/var/www/clients/client1/web1/web/libraries",
// more items
);
foreach ($choice as $choice_key => $choice_item) {
$exists_in_list = FALSE;
foreach ($list as $list_key => $list_item) {
if (strpos($list_item, $choice_item) !== FALSE) {
//$choice_item is string-contained inside $list_item:
$exists_in_list = TRUE;
//Do some processing on $list (while "$list_key" is in scope). For example:
unset($list[$list_key]); //removes the matching items from $list
//...
break;
}
}
if ($exists_in_list) {
//Do post-processing on $choice. For example:
unset($choice[$choice_key]); //removes the matching items from $choice
//...
}
}
echo '$choice is now ';
print_r($choice);
echo '$list is now ';
print_r($list);
The $result is:
//Option 1:
Array //$result == $bigger - $smaller
(
[2] => C
[3] => D
[4] => E
[5] => F
)
//Option 2:
Array //$smaller - $bigger
(
)
Array //$bigger - $smaller
(
[2] => C
[3] => D
[4] => E
[5] => F
)
//Option 3:
$choice is now Array
(
)
$list is now Array
(
[2] => /var/www/clients/client1/web1/web/includes
[3] => /var/www/clients/client1/web1/web/libraries
)
-
thanks for your answer, to be honest, I never used in_array before. I use strpos because I want to compare webserver paths/urls. If you could give example ?durduvakis– durduvakis08/06/2012 22:26:31Commented Aug 6, 2012 at 22:26
-
thanks let me try this ! (yes I want whatever is in $choice to be out)durduvakis– durduvakis08/06/2012 22:47:24Commented Aug 6, 2012 at 22:47
-
If you only want to remove items from one array, you can use "array_diff" and be done with it. Otherwise, if the items in both arrays are equal, you can simply use "in_array" since that uses equality. But if the items are not strictly equal (but are perhaps substrings of one another, you'll need instead to use "strpos".EthanB– EthanB08/06/2012 22:50:46Commented Aug 6, 2012 at 22:50
-
while I am trying your example, I read your answer. I was using strpos because I want to exclude any url/path that starts with say: '/var/www/clients/client1/web1/web/images' plus all it's sub strings - directories and files within it and to make sure that no other path exists like this one on the directory. Example if I used 'images' only to compare, there might be many directories or files with this in name, and that would remove/exclude all those.durduvakis– durduvakis08/06/2012 23:06:18Commented Aug 6, 2012 at 23:06
-
you are very helpful and thanks a lot. I will need a little time to understand this and put it in my code. thank you very much!durduvakis– durduvakis08/06/2012 23:33:40Commented Aug 6, 2012 at 23:33
continue
inside loops? it will allow you to bypass the current loop without doing any more actions