multi-sort of associative array in PHP
arrays, php, sorting
Solution
You can use array_multisort
<?php
$arr = Array
(
'banana' => 2,
'cherry' => 1,
'orange' => 3,
'grapefruit' => 1,
'apple' => 1
);
$values = array_values($arr);
$keys = array_keys($arr);
//first sort by values desc, then sort by keys asc
array_multisort($values, SORT_DESC, $keys, SORT_ASC, $arr);
print_r($arr);
// output:
/*
Array
(
[orange] => 3
[banana] => 2
[apple] => 1
[cherry] => 1
[grapefruit] => 1
)
*/
?>
It works like this:
- for each column used to sort (values and keys for you), create new 1d array with its contents
- pass those 1d arrays to array_multisort function in your sorting order (so $values first, then $keys), add sort order for each array
- the last argument has to be the array which you want to sort
(Perhaps you will find this explanation easier to understand)
Problem
Consider the following associative array ``` $arr = Array ( [banana] => 2 [cherry] => 1 [orange] => 3 [grapefruit] => 1 [apple] => 1 ) ``` I want to sort it in a way that would be similar to the PLSQL term: `A DESC, B ASC` (where A is the value and B is the key) meaning: ``` $arr = Array ( [orange] => 3 [banana] => 2 [apple] => 1 [cherry] => 1 [grapefruit] => 1 ) ``` so that orange and banana are first because of the VALUE, but then I have apple, cherry and grapefruit in alphabetical order because they have the same VALUE. What I tried: 1. to run ksort() and then asort()/rsort() hoping that the second sort will bump up orange and banana to the beginning of the array without messing up the alphabetical sort of the other 3 items. I was wrong. it does messes everything up. So I checked out: 2. sort functions and array_multisort(). But apparently it sorts several arrays at once, or a multi-dimensional array. 3. I also tried to define the following compare function: ``` function cmp($a, $b) { foreach ($a as $key1 => $val1) { foreach ($b as $key2 => $val2) { if($val1 == $val2){ return strcmp($key1,$key2); } else if ($val1 > $val2){ return 1; } else{ // $val1 < $val2 return -1; } } } } ``` and call it with usort() but it also didn't work. So my question is: is there a PHP method that implements the requested behavior? For Eugen: I tried it and it doesn't work before sorting: ``` Array ( [lamb] => 3 [rule] => 1 [children] => 1 [teacher] => 2 [eager] => 1 ) ``` and after sorting: ``` Array ( [children] => 1 [eager] => 1 [rule] => 1 [teacher] => 2 [lamb] => 3 ) ```