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
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" }
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.
PHP use quicksort as base sorting-algorithms. You hae two options:
I have programmed a package porth/avalanchesort (https://github.com/porthd/avalanchesort) on github, which contains a recursive naturell-merge-sort. You can use your own comparsionfunction and your own data-structure. The package contains an example for associative arrays and for list-arrays.
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);
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.
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];
}