2

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?

4
  • stackoverflow.com/questions/10271708/how-does-array-udiff-work Commented Jul 1, 2013 at 10:01
  • 1
    Even if I add if( $value == $value2 ) { return 1; } else { return 0; } it still returns a massive list of different numbers which means my outputted array is completely empty even though all the values are equal. Commented Jul 1, 2013 at 10:06
  • Your callback function is to blame: int callback ( mixed $a, mixed $b ) should be its signature. Though I'd say array_map or list is a better fit for your use-case Commented Jul 1, 2013 at 10:08
  • This here is about sorting arrays, but the basic concept of a comparison function is the same: stackoverflow.com/a/17364128/476 Read for more of a conceptual introduction. Commented Jul 1, 2013 at 10:21

3 Answers 3

3

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.

Sign up to request clarification or add additional context in comments.

8 Comments

Ah right, ok that makes sense about why I am seeing the long list now to a point... However it still doesn't seem to compare the first value of "2" with anything and the comparison 3 - 2 is made 3 times? What doesn't make sense is why replacing the echo statement with if( $value == $value2 ) { return 1; } else { return 0; } is returning a blank array?
It's returning a blank array because there is no difference in the two arrays. Because there is no difference there is nothing to return. Try adding another value to $newArray only.
Ok... I wasn't aware a blank array would be returned if they were blank... I was under the assumption that it would just return any values that are similar in the arrays... Adding another value to the first array made it return as expected... Thanks for the help Jim!
From the manual: "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." (i.e. you're returning the wrong value when $a<$b and when $a=$b) and the arrays are the same so the difference should be blank,.
Ok, no I dont think I quite understand it still after further playing... If I compare 2 arrays one with the values 1,2,3 and the other with values 1,2,3,4,5 and run a simple if( $value == $value2 ) { return 0; } return 1; in the callback function why does it return just 2 and 3? Would it not either return 1,2,3 or 4,5... I dont understand why it returns just 2,3...
|
1

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:

enter image description here

Comments

0

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,
)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.