12

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
)
3
  • How will you be using the resulting array? Commented Jun 16, 2012 at 9:03
  • @Galen in a very sophisticated and powerful way that was never seen on earth ;) Commented Jun 16, 2012 at 9:07
  • 1
    Regarding your first approach, it didn't work because PHP sorting is not stable (i.e. maintains order on equal values). Commented Jun 16, 2012 at 9:47

3 Answers 3

13

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)

Sign up to request clarification or add additional context in comments.

3 Comments

I don't know why you got -1, you got +1 from me as your solution indeed works, thanks!!!
@alfasin thanks :), people're so fast in downvoting and don't event explain why...
If we want to add multiple Sorting flags for each element we want to sort by, will it work?
3
function polysortcmp($a, $b) {
  if ($a[1]<$b[1]) return 1;
  if ($a[1]>$b[1]) return -1;
  if ($a[0]<$b[0]) return -1;
  if ($a[0]>$b[0]) return 1;
  return 0;
}


function polysort(&$arr) {
  foreach ($arr as $k=>$v) $arr[$k]=array($k,$v);
  uasort($arr, "polysortcmp");
  foreach ($arr as $k=>$v) $arr[$k]=$v[1];
}

4 Comments

it doesn't work. I update the question to show you what is the result if I try it your way.
Sorry, misread you: I sorted by key first, then value - updated my answer.
Now it sorts alphabetically, but the VALUES are in ASC order instead of DESC. I updated my question to show you the current output of your code. You can take the example I gave and run it.
OK, third time is a charm, again updated my answer. For your information: the sort order is in polysortcmp() with $a[1] being the value and $a[0] being the key.
0

array sorting function arsort used..

$arr = array(        
        'banana' => 2,
        'cherry' => 1,
        'orange' => 3,
        'grapefruit' => 1,
        'apple' => 1
    );

arsort($arr);
print_r($arr);

Output

Array ( [orange] => 3 [banana] => 2 [apple] => 1 [grapefruit] => 1 [cherry] => 1 ) 

1 Comment

I tried arsort() and it doesn't work. it might work on that specific example I gave - but it will not work on general case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.