Reputation: 8112
I have the following simple function to try and understand the array_udiff()
function.
function udiffCompare( $value, $value2 )
{
echo "$value - $value2<br />";
}
$newArray = ['value2' => 2, 'value3' => 3, 'value4' => 4];
$newArray2 = ['value2' => 2, 'value3' => 3, 'value4' => 4];
array_udiff( $newArray, $newArray2, 'udiffCompare' );
I would expect this to simply return:
2 - 2
3 - 3
4 - 4
However it returns:
3 - 2
4 - 3
3 - 2
4 - 3
4 - 4
4 - 3
4 - 3
3 - 2
This leads me to believe there is something I am really not understanding here about how array_udiff()
works.
Even if I replace the echo statement above with:
if( $value == $value2 ) { return 1; } else { return 0; }
the outputted array is completely empty even though all the values passed to the function are equal.
Could someone shine a light please?
Upvotes: 2
Views: 1921
Reputation: 47991
Under the hood, PHP's array_u*()
functions perform sorting to improve filtration performance. Values will be compared, two at a time, until all values are sorted, then PHP can efficiently determine which elements should be kept/removed.
From the manual:
Caution The sorting callback must handle any value from any array in any order, regardless of the order they were originally provided. This is because each individual array is first sorted before being compared against other arrays.
In your script, you are echoing the function arguments, but you are not returning any meaningful result (and array_u*()
functions all expects the result of a 3-way comparison). This means that all compared pairs return 0
-- no tie breaks occur and therefore no performance boost. Because 0
evaluations mean "remove the element" with array_udiff()
, all elements are removed.
In contrast, if you implement and return a 3-way evaluation for each pair of values, you will see different echoed pairs because tie breaks are required.
Also notice that the first and second arguments are not exclusively pulled from the input array with the corresponding position. In other words, the $a
and $b
values may come from any input array. This is important because array_diff()
and array_intersect()
functions can receive two or more input arrays.
Here's a demonstration with different input values to give better clarity. Demo
$array1 = [1, 2, 3];
$array2 = [4, 5, 6];
function udiffCompare($a, $b)
{
echo "Compare $a and $b\n";
}
var_export(
array_udiff($array1, $array2, 'udiffCompare')
);
echo "\n---\n";
function udiffCompare2($a, $b)
{
echo "Compare $a and $b\n";
return $a <=> $b;
}
var_export(
array_udiff($array1, $array2, 'udiffCompare2')
);
Output:
Compare 1 and 2
Compare 2 and 3
Compare 4 and 5
Compare 5 and 6
Compare 1 and 4
Compare 1 and 2
Compare 2 and 3
array (
)
---
Compare 1 and 2
Compare 2 and 3
Compare 4 and 5
Compare 5 and 6
Compare 1 and 4
Compare 1 and 2
Compare 2 and 4
Compare 2 and 3
Compare 3 and 4
array (
0 => 1,
1 => 2,
2 => 3,
)
Upvotes: 0
Reputation: 20286
You didn't write proper callback function for array_udiff().
The comparison function must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.
Moreover mathematical difference of these 2 sample arrays you given is NULL That is why you will get empty result set if you use this function. Check it on array_diff();
The gray area shows the difference of two collections:
Upvotes: 1
Reputation: 22656
array_udiff
computes the difference of the two arrays. That is all entries in $newArray
which are not in $newArray2
. In this case the result is an empty array because there is no difference.
The output you are seeing is because you are echoing each value that is being compared. The reason this is a larger list is because, in order to find out the difference array_udiff
has to compare every value in $newArray
with every value in $newArray2
.
Upvotes: 3