I'm using usort to sort an array with an associative array within each element.
When all of the values I am sorting on in the array are the same then it still changes the position of the elements in the array, is there a way to prevent this?
For example this:
array(
array('name' => 'Ben', 'authn_weight' => 85.3),
array('name' => 'Josh', 'authn_weight' => 85.3),
array('name' => 'Fred', 'authn_weight' => 85.3)
);
May be changed to this:
array(
array('name' => 'Josh', 'authn_weight' => 85.3),
array('name' => 'Ben', 'authn_weight' => 85.3),
array('name' => 'Fred', 'authn_weight' => 85.3)
);
This is the sort function:
private function weightSortImplementation($a, $b){
$aWeight = $a['autn_weight'];
$bWeight = $b['autn_weight'];
if ($aWeight == $bWeight) {
return 0;
}
return ($aWeight < $bWeight) ? 1 : -1;
}
I have checked that the weightSortImplementation
function is always returning 0 showing that they are the same. So why is this still reordering the array?
Although there is a basic array sorting function, called simply sort(), it makes no attempt to preserve the values of your keys and so usually does more harm than good. In its place are asort() and ksort(), which are very similar- asort() sorts an array by its values, whereas ksort() sorts an array by its keys.
Sorting functions in PHP are currently unstable, which means that the order of “equal” elements is not guaranteed.
The usort() function in PHP sorts a given array by using a user-defined comparison function. This function is useful in case if we want to sort the array in a new manner. This function assigns new integral keys starting from zero to the elements present in the array and the old keys are lost.
The arsort() function sorts an associative array in descending order, according to the value. Tip: Use the asort() function to sort an associative array in ascending order, according to the value. Tip: Use the krsort() function to sort an associative array in descending order, according to the key.
Aha, a case for the Schwartzian Transform.
It basically consists of three steps:
Here it is (I've tweaked it to your particular use case):
function decorate(&$v, $k)
{
$v['authn_weight'] = array($v['authn_weight'], $k);
}
function undecorate(&$v, $k)
{
$v['authn_weight'] = $v['authn_weight'][0];
}
array_walk($a, 'decorate');
usort($a, 'weightSortImplementation');
array_walk($a, 'undecorate');
The trick is in the following assertion:
array($x, 0) < array($x, 1)
This is what keeps the correct order of your array. And, no recursion required :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With