Home » Php » arrays – How to have a stable sort in PHP with arsort()?

arrays – How to have a stable sort in PHP with arsort()?

Posted by: admin July 12, 2020 Leave a comment

Questions:

i need to sort an array in php based on value, array use some numbers for keys and values, for example like this:

$a = array(70 => 1 ,82 => 5  ,61 => 3 ,55 => 1 ,34 => 2 ,53 => 2 ,21 => 4 ,13 => 5);

i like to sort it like this:

Array
(
    [82] => 5
    [13] => 5
    [21] => 4
    [61] => 3
    [34] => 2
    [53] => 2
    [70] => 1
    [55] => 1
)

i used arsort and it worked, but there is a problem because this function make change defult sorted keys and sort array to:

Array
(
    [13] => 5
    [82] => 5
    [21] => 4
    [61] => 3
    [53] => 2
    [34] => 2
    [55] => 1
    [70] => 1
)
How to&Answers:

Construct a new array whose elements are the original array’s keys, values, and also position:

$temp = array();
$i = 0;
foreach ($array as $key => $value) {
  $temp[] = array($i, $key, $value);
  $i++;
}

Then sort using a user-defined order that takes the original position into account:

uasort($temp, function($a, $b) {
 return $a[2] == $b[2] ? ($a[0] - $b[0]) : ($a[2] < $b[2] ? 1 : -1);
});

Finally, convert it back to the original associative array:

$array = array();
foreach ($temp as $val) {
  $array[$val[1]] = $val[2];
}

Answer:

This is because the sort family of functions are not stable. If you need the sort to be stable then you either have to implement it yourself, or iterate over the sorted result and “correct” the positions of the elements using array_splice.

Answer:

For reference, I’ve put a set of stable sort variants of builtin PHP functions on Github: https://github.com/vanderlee/PHP-stable-sort-functions, based on @Barmar’s solution and a few other tricks.

Answer:

It is kinda a big workaround, but it does work:

$a = array(70 => 1 ,82 => 5  ,61 => 3 ,55 => 1 ,34 => 2 ,53 => 2 ,21 => 4 ,13 => 5);
$b = max($a);
$c = min($a);
$d = 0;
$sorted_list = array();
while($b >= $c){
    foreach($a as $key => $value){
        if($value == $b){
            $sorted_list[$key] = $value;
        }
    }
    $b--;
}

vardump output:

array(8) { [82]=> string(1) "5" [13]=> string(1) "5" [21]=> string(1) "4" [61]=> string(1) "3" [34]=> string(1) "2" [53]=> string(1) "2" [70]=> string(1) "1" [55]=> string(1) "1" } 

Answer:

Simple solution with array_multisort.

$assoc = [
    70 => 1,
    82 => 5,
    61 => 3,
    55 => 1,
    34 => 2,
    53 => 2,
    21 => 4,
    13 => 5,
];

$keys = array_keys($assoc);
array_multisort($assoc, SORT_DESC, range(1, count($assoc)), $keys);
$assoc = array_combine($keys, $assoc);

print_r($assoc);

Answer:

You can create your own sorting function to meet your customized sorting criteria and then use usort() to iterate all over the array using the function you created to sort the array.