Depending on the scope of your task, it may be necessary to only remove elements from the first array which are "one-for-one" represented in the second array. In other cases, it may be appropriate to cross-check the differences in a "one-for-one" manner for both arrays and combine the remaining elements.
Consider this altered sample data set:
$test1 = [
"blah1",
"blah1",
"blah2",
"blah4",
"blah5"
];
$test2 = [
"blah1", // under-represented
"blah2", // equally found
"blah3", // not found
"blah4", // over-represented
"blah4", // "
];
Below are four different functions (with indicative names) to offer varied utility.
Codes: (Demo)
unilateral difference (iterated array searches):
function removeBValuesFromA(array $a, array $b): array
{
foreach ($b as $bVal) {
$k = array_search($bVal, $a);
if ($k !== false) {
unset($a[$k]);
}
}
return array_values($a);
}
bilateral difference (iterated array searches):
function bidirectionalDiff(array $a, array $b): array
{
foreach ($b as $bKey => $bVal) {
$aKey = array_search($bVal, $a);
if ($aKey !== false) {
unset($a[$aKey], $b[$bKey]);
}
}
return array_merge($a, $b);
}
unilateral difference (condense-compare-expand):
function removeBValuesFromAViaCounts(array $a, array $b): array
{
$toRemove = array_count_values($b);
$result = [];
foreach (array_count_values($a) as $k => $count) {
array_push(
$result,
...array_fill(
0,
max(0, $count - ($toRemove[$k] ?? 0)),
$k
)
);
}
return $result;
}
or
function removeBValuesFromAViaCounts(array $a, array $b): array
{
$toRemove = array_count_values($b);
$result = [];
foreach (array_count_values($a) as $k => $count) {
for ($i = 0; $i < $count - ($toRemove[$k] ?? 0); ++$i) {
$result[] = $k;
}
}
return $result;
}
bilateral difference (condense-compare-expand):
function bidirectionalDiffViaCounts(array $a, array $b): array
{
$bCounts = array_count_values($b);
$result = [];
foreach (array_count_values($a) as $k => $count) {
array_push(
$result,
...array_fill(
0,
abs($count - ($bCounts[$k] ?? 0)),
$k
)
);
unset($bCounts[$k]);
}
foreach ($bCounts as $k => $count) {
array_push(
$result,
...array_fill(0, $count, $k)
);
}
return $result;
}
Execution:
var_export([
'removeBValuesFromA' => removeBValuesFromA($test1, $test2),
'bidirectionalDiff' => bidirectionalDiff($test1, $test2),
'removeBValuesFromAViaCounts' => removeBValuesFromAViaCounts($test1, $test2),
'bidirectionalDiffViaCounts' => bidirectionalDiffViaCounts($test1, $test2),
]);
Outputs:
array (
'removeBValuesFromA' =>
array (
0 => 'blah1',
1 => 'blah5',
),
'bidirectionalDiff' =>
array (
0 => 'blah1',
1 => 'blah5',
2 => 'blah3',
3 => 'blah4',
),
'removeBValuesFromAViaCounts' =>
array (
0 => 'blah1',
1 => 'blah5',
),
'bidirectionalDiffViaCounts' =>
array (
0 => 'blah1',
1 => 'blah4',
2 => 'blah5',
3 => 'blah3',
),
)
$array1 = [ 'a', 'b', 'c' ]
and$array2 = [ 'd' ]
. The output should be the same as$array1
, but will be[ 'b', 'c' ]
because thearray_search()
will returnsfalse
when looking ford
, and theunset()
will drop the first key of$array1
becausefalse == 0
. Anif
should helps on it (gist, run). – Marten