Forum Moderators: coopster

Message Too Old, No Replies

Filtering with array diff()

Creating 3rd array which is the 1st array minus 2nd array

         

Wittner

9:06 am on Feb 2, 2011 (gmt 0)

10+ Year Member



Hi,

I have two arrays. The 1st is a list of items like so:

1st Array:

[0] => Array
(
[item_name] => Big widget
[item_number] => 1001
[item_color] => Blue
)

[2] => Array
(
[item_name] => Little widget
[item_number] => 1006
[item_color] => Green
)

[3] => Array
(
[item_name] => Medium widget
[item_number] => 1022
[item_color] => Yellow
)

[4] => Array
(
[item_name] => Massive widget
[item_number] => 1012
[item_color] => Teal
)

[5] => Array
(
[item_name] => Weeny widget
[item_number] => 1055
[item_color] => Orange
)



The second array is a list of items I would like excluded from the first array.

2nd Array:

[0] => Array
(
[item_name] => Massive widget
[item_number] => 1012
[item_color] => Teal
)

[1] => Array
(
[item_name] => Little widget
[item_number] => 1006
[item_color] => Green
)



And the 3rd array is what I would like to end up with - an array which is the first array minus the objects in the second array.

3rd Array:

[0] => Array
(
[item_name] => Big widget
[item_number] => 1001
[item_color] => Blue
)

[1] => Array
(
[item_name] => Medium widget
[item_number] => 1022
[item_color] => Yellow
)

[2] => Array
(
[item_name] => Weeny widget
[item_number] => 1055
[item_color] => Orange
)


The first two arrays are produced from a DB of products and the third will be the result set of (array1)-(array2). I am trying to use array_diff() or one of the other array functions to do this but to no avail. Could someone point me in the right direction? Do I have to resort to a messy foreach() and do the deletions 'manually' or is there a better method. A pointer in the right direction would be good, not asking anyone to code the whole thing (unless you feel especially kind today!) ;-)

many thanks,

Wittner

Wittner

10:54 am on Feb 3, 2011 (gmt 0)

10+ Year Member



Just a follow-up to this. I received no replies about how to use array_diff() and could not find an answer on the Internet anywhere so this is what I came up with in the end. It uses foreach loops which I didn't really want to use, but I present my solution here for anyone else who has the problem I had. This code just shows how to loop through one array using another for matching. In the real world example I will use unset() to remove the record upon a match being found. This code is just to illustrate the principle. It can be run as-is and will echo out some comments to show how it works:


<?php

$availableNames = array
(
0 => array
(
'id' => '1001',
'name' => 'Brian',
'color' => 'Blue'
),
1 => array
(
'id' => '1002',
'name' => 'Paul',
'color' => 'Black'
),
2 => array
(
'id' => '1003',
'name' => 'Peter',
'color' => 'Green'
),
3 => array
(
'id' => '1004',
'name' => 'Mary',
'color' => 'Pink'
)
);

$namesForDeletion = array
(
0 => array
(
'id' => '1001',
),
1 => array
(
'id' => '1003',
)
);



echo '<pre><br />';
echo 'Original arrays: <br />';
echo 'Available names <br />';
print_r($availableNames);
echo 'Names for deletion <br />';
print_r($namesForDeletion);

echo '<p>&nbsp;</p>Results: <br />';

foreach($namesForDeletion as $key => $value)
{
echo $key . 'Looking for... ' . $namesForDeletion[$key]["id"] . '<br />';
foreach($availableNames as $nameKey => $nameValue)
{
echo $nameKey . ' - ' . $availableNames[$nameKey]["id"];
if (in_array($namesForDeletion[$key]["id"], $availableNames[$nameKey])) {echo 'Deleting ' . $availableNames[$nameKey]["name"];}
echo '<br />';
}
}
echo '</pre>';
?>


hope it helps someone,

cheers,

Wittner

coopster

1:56 pm on Feb 3, 2011 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



Is there no way to eliminate the duplicates in the query rather than the application? I would think it would be much easier in the query.

Wittner

2:13 pm on Feb 3, 2011 (gmt 0)

10+ Year Member



Hi coopster. I really don't think so - at least in my particular instance. In real life this is a 'booking' type scenario and the DB table which holds the bookings (i.e. the equivalent of the 2nd array above) only has data present where a booking has been made so I can't query it to show me all the 'items' where a booking hasn't been made. Therefore, I have to get all the bookings and use that data to filter out all the items which are not booked (if that makes sense). That's not to say you're wrong, but my head can't come up with any other scenario than the array comparison.

coopster

2:24 pm on Feb 3, 2011 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



Makes perfect sense. It's like having a library of products and orders. I can select from all the products and LEFT JOIN to the orders WHERE the product identifier IS NULL. This tells me which products currently are not being ordered.

Wittner

5:16 pm on Feb 9, 2011 (gmt 0)

10+ Year Member



Hi Coopster. Couldn't get the LEFT JOIN working on a table which had no data in it for the relevant foreign keys, but, your idea of doing things on the SQL side paid off. I now use an equivalent to this:


SELECT blah, blah1, blah2
FROM Table1
WHERE key NOT IN
(SELECT thing1, thing2, thing3
FROM Table2
WHERE whatever etc.
)


works a charm and is FAR faster than the array approach (I was sure that array manipulation would be faster!). Anyway, thanks for the idea SOLVED,

cheers,

Wittner

coopster

8:16 pm on Feb 9, 2011 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



Excellent! Glad it worked out for you.