Reputation: 10240
I'm trying to understand how the items from my array are passed to my value compare function when using usort()
. A printout of the values of $x
and $y
for each iteration follows:
Iteration 1:
// $x
array(2) { ["k1"]=> int(21) ["k2"]=> string(1) "e" }
// $y
array(2) { ["k1"]=> int(920) ["k2"]=> string(1) "z" }
Iteration 2:
// $x
array(2) { ["k1"]=> int(842) ["k2"]=> string(1) "t" }
// $y
array(2) { ["k1"]=> int(21) ["k2"]=> string(1) "e" }
Iteration 3:
// $x
array(2) { ["k1"]=> int(920) ["k2"]=> string(1) "z" }
// $y
array(2) { ["k1"]=> int(21) ["k2"]=> string(1) "e" }
Iteration 4:
// $x
array(2) { ["k1"]=> int(842) ["k2"]=> string(1) "t" }
// $y
array(2) { ["k1"]=> int(920) ["k2"]=> string(1) "z" }
My data:
$data = array(
array( 'k1' => 920, 'k2' => 'z' ),
array( 'k1' => 21, 'k2' => 'e' ),
array( 'k1' => 842, 'k2' => 't' )
);
My custom function:
function value_compare_func( $x, $y ) {
if ( $x['k1'] > $y['k1'] ) {
return true;
} elseif ( $x['k1'] < $y['k1'] ) {
return false;
} else {
return 0;
}
}
Sort the array:
usort( $data, 'value_compare_function' );
For the first iteration, $x['k1']
is $data[1]['k1']
and $y['k1']
is $data[0][k1]
. Why aren't the items from my $data
array passed to value_compare_func()
in order? For example, I would have expected $x['k1']
to be $data[0]['k1']
and $y['k1']
to be $data[1]['k1']
for the first iteration, but this isn't the case.
Upvotes: 4
Views: 139
Reputation: 11943
The answer to how these items are passed to the comparison function would require understanding the quicksort algorithm. The gist of it is that some element in the array is assigned as a pivot (it could be any element at all really, but in efficient implementation's it's typically the median element) and then comparison on either side of the pivot is done to sort the array.
This is the underlying implementation of usort
in PHP, basically.
So trying to observe the order in which elements are passed to the comparison function is relatively useless. The order is completely unimportant. What's important is that you can rest assured they will always be sorted correctly according to what your callback function returns.
The important thing to note here is that the manual explicitly warns against returning values from the callback that are not integers for a very specific reason (they will be cast to integers) and in your example here you are returning a boolean false
from the callback which will become 0
when cast to an integer
. Since 0
indicates both values are equal you will not and should not expect a properly sorted array here.
Always make sure to return an integer value of 1
when $a > $b
, an integer value of -1
, when $a < $b
and an integer value of 0
when $a == $b
from your callback.
Upvotes: 2
Reputation: 350272
The compare function should return a numerical value. Since you return booleans, the comparison becomes unpredictable as false == 0
and so the distinction between the two is lost in sorting.
You should change your code as follows:
function value_compare_func( $x, $y ) {
if ( $x['k1'] > $y['k1'] ) {
return 1;
} elseif ( $x['k1'] < $y['k1'] ) {
return -1;
} else {
return 0;
}
}
... and the results will be more logical.
Upvotes: 0