Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

php

sorting

usort

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?

like image 563
Chris Avatar asked Aug 28 '12 16:08

Chris


People also ask

What is the difference between the sort and Usort functions?

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.

Is PHP Usort stable?

Sorting functions in PHP are currently unstable, which means that the order of “equal” elements is not guaranteed.

How does Usort work in PHP?

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.

How do you sort an associative array in PHP?

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.


1 Answers

Aha, a case for the Schwartzian Transform.

It basically consists of three steps:

  1. decorate; you turn every value into an array with the value as the first element and the key/index as the second
  2. sort (as per normal)
  3. 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 :)

like image 89
Ja͢ck Avatar answered Oct 20 '22 00:10

Ja͢ck