Reputation: 189
There are two arrays, that has say below data -
$a = Array(a,b,d,c,e,a);
$b = Array(a,a,d,e,c,a);
I want to remove an instance of array values as a pair, i.e., it should exist in array 'a' and array 'b' If you understand, I want to remove elements that form similar pair.
The output should finally be like -
$a = [b]; $b = [a];
as those are the only elements that left which doesn't make a pair.
I tried using array_diff, but it's not getting me the expected output -
$arr1 = array_diff($aArr, $bArr);
$arr2 = array_diff($bArr, $aArr);
print_r($arr1);
print "<br>";
print_r($arr2);
$res = count($arr1) + count($arr2);
print $res;
This code is working fine, when the input is
Array ( c, d, e )
Array ( a, b, c )
But will give zero for input as
Array ( a, a, b, d, e, c, a )
Array ( b, a, b, d, e, c, a )
How can I achieve this? Thanks.
Upvotes: 4
Views: 103
Reputation: 313
I know this is answered. But the accepted answer is slower than my more complicated solution (if order does not matter).
$a = ['a', 'b', 'd', 'c', 'e', 'a'];
$b = ['a', 'a', 'd', 'e', 'c', 'a'];
$ha = $hb = [];
foreach ($a as $v) $ha[$v]++;
foreach ($b as $v) $hb[$v]++;
foreach (range('a', 'z') as $l) {
if (empty($ha[$l])) continue;
if (empty($hb[$l])) continue;
if ($ha[$l] > $hb[$l]) {
$ha[$l] = $ha[$l] - $hb[$l];
unset($hb[$l]);
continue;
}
$hb[$l] = $hb[$l] - $ha[$l];
unset($ha[$l]);
}
$a = [];
$b = [];
foreach ($ha as $l => $n) $a = array_merge($a, array_fill(0, $n, $l));
foreach ($hb as $l => $n) $b = array_merge($b, array_fill(0, $n, $l));
var_dump([$a, $b]);
Above code is O(N) as the accepted answer is O(N^2). So choose from simplicity or speed.
Upvotes: 0
Reputation: 3792
You can use array_filter
and passing by reference:
$a = ['a', 'b', 'd', 'c', 'e', 'a'];
$b = ['a', 'a', 'd', 'e', 'c', 'a'];
$a = array_filter($a, function ($element) use (&$b) {
if (($key = array_search($element, $b)) !== false) {
unset($b[$key]);
return false;
}
return true;
});
Here is demo.
With array_filter
we can filter array based on predicate function (a function that returns true for elements, that should be kept in the result, and false otherwise). In our case, this function uses $b
in order to determine to keep a $a
element or not. If we in clause $b
by reference, we can remove pairs along the way.
Upvotes: 3
Reputation: 3796
you can loop through every array like this
foreach ($a as $aItem){
if(!in_array($aItem, $b)){
$arr1[] = $aItem;
}
}
var_dump($arr1);
Upvotes: 0
Reputation: 962
This works with arrays of different sizes and disregards values positions.
$arr1 = removePairs($aArr, $bArr);
$arr2 = removePairs($bArr, $aArr);
print_r($arr1);
print "<br>";
print_r($arr2);
$res = count($arr1) + count($arr2);
print $res;
function removePairs($a, $b)
{
$r = array();
foreach ($a as $index => $value) {
$found = array_search($value, $b);
if ($found !== false) {
$b[$found] .= '-';
} else {
$r[] = $value;
}
}
return $r;
}
Upvotes: 0