0

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.

asked Aug 6, 2012 at 22:16
4
  • 1
    Can you provide an example of your two arrays? Commented Aug 6, 2012 at 22:20
  • Another consideration is where the data is coming from. If you're getting this data as the result of queries, perhaps it would be more concise to leverage the power of the DB to make this happen. Need more info! Commented Aug 6, 2012 at 22:25
  • I'm not sure what you really want todo, but ever used continue inside loops? it will allow you to bypass the current loop without doing any more actions Commented Aug 6, 2012 at 22:28
  • yes I have used continue; with the same results. I just turned to if/else because I now also do things when !--false. I will edit my post to give example of what the arrays include. thanks for the help! Commented Aug 6, 2012 at 22:32

1 Answer 1

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
)
answered Aug 6, 2012 at 22:23
7
  • 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 ? Commented Aug 6, 2012 at 22:26
  • thanks let me try this ! (yes I want whatever is in $choice to be out) Commented 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". Commented 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. Commented 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! Commented Aug 6, 2012 at 23:33

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.