Just for the fun of it, something that just came to mind. 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]--;
});
It has the advantage that it only walks over each of your arrays just once.
See it in action.
How it works:
First the frequencies of each element in the second array are counted. This gives us an arrays where keys are the elements that should be removed from $a
and values are the number of times that each element should be removed.
Then array_filter
is used to examine the elements of $a
one by one and remove those that should be removed. The filter function uses empty
to return true
if there is no key equal to the item being examined or if the remaining removal count for that item has reached zero; empty
's behavior fits the bill perfectly.
If neither of the above holds then we want to return false
and decrement the removal count by one. Using false || !$counts[$o]--
is a trick in order to be terse: it decrements the count and always evaluates to false
because we know that the count was greater than zero to begin with (if it were not, ||
would short-circuit after evaluating empty
).
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…