Just for fun, something that just occurred to me. Will work as long as your arrays contain strings:
$a = array('a','b','a','c'); $b = array('a'); $counts = array_count_values($b); $a = array_filter($a, function($o) use (&$counts) { return empty($counts[$o]) || !$counts[$o]--; });
The advantage is that it only iterates over each of your arrays only once.
Look at the action .
How it works:
First, the frequencies of each element in the second array are taken into account. This gives us arrays where the keys are the elements that should be removed from $a , and the values ββare the number of times each element should delete.
array_filter is then used to examine $a elements one at $a and remove those that should be removed. The filter function uses empty to return true if there is no key equal to the element being checked, or if the remaining deletion amount for this element has reached zero; empty behavior is great for counting.
If none of the above is true, we want to return false and reduce the amount of deletion by one. Using false || !$counts[$o]-- false || !$counts[$o]-- is a trick to be brief: it decreases the counter and always evaluates to false , because we know that the counter was greater than zero to start (if it werenβt, || would be short-circuited after evaluating empty ).
source share