PHP usort reorders array the sort value is the same for all

php, sorting, usort

Solution

Aha, a case for the Schwartzian Transform.

It basically consists of three steps:

- decorate; you turn every value into an array with the value as the first element and the key/index as the second

- sort (as per normal)

- undecorate; you reverse step 1

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

Problem

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?

Original source

Related problems