0

Hey guys I'm trying to reverse sort a multidimensional array with usort but am messing up somewhere. Here's my code:

$array = array(
    array(123 => 'foo'), // duplicate
    array(124 => 'foo'),
    array(127 => 'foo'),
    array(126 => 'foo'),
    array(123 => 'foo'), // duplicate
    array(125 => 'foo'),
);

function rcmp($a, $b) {
    if($a == $b) {
        return 0;
    }
    return ($a < $b) ? -1 : 1;
}

usort($array, 'rcmp');

print_r($array);

/*
    Array
    (
        [0] => Array ( [126] => foo) )
        [1] => Array ( [125] => foo) )
        [2] => Array ( [127] => foo) )
        [3] => Array ( [123] => foo) )
        [4] => Array ( [124] => foo) )
        [5] => Array ( [123] => foo) )
    )
*/

I am expecting

/*
    Array
    (
        [0] => Array ( [127] => foo) )
        [1] => Array ( [126] => foo) )
        [2] => Array ( [125] => foo) )
        [3] => Array ( [124] => foo) )
        [4] => Array ( [123] => foo) )
        [5] => Array ( [123] => foo) )
    )
*/

What am I doing wrong?

3
  • I may be missing something, but it seems that you are trying to sort things that are all of the same value. Commented Mar 29, 2013 at 22:26
  • The keys are all different Commented Mar 29, 2013 at 22:27
  • So basically you want to do a krsort on your sub-array ? Edit : I misread your code... I get it now :) Commented Mar 29, 2013 at 22:32

3 Answers 3

2

If you want to compare on the array's indexes, you must extract the indexes in the comparison function and reverse the comparison for descending order

function rcmp($a, $b) {
    $a = array_keys($a);
    $b = array_keys($b);

    if($a[0] == $b[0]) {
        return 0;
    }

    return ($a[0] < $b[0]) ? 1 : -1;
}
Sign up to request clarification or add additional context in comments.

Comments

2

When your comparison function rcmp is invoked, its arguments $a and $b are arrays so your equality and less-than operators have arrays as their operands.

The equality operator on arrays works like this:

TRUE if $a and $b have the same key/value pairs.

The less-than comparison works like this:

Array with fewer members is smaller, if key from operand 1 is not found in operand 2 then arrays are uncomparable, otherwise - compare value by value.

"Uncomparable" means the comparison evaluates to null, which in turn causes rcmp to return 1.

So what ends up happening is that when $a and $b are not identical arrays rcmp always returns 1 (i.e. considers that $a is greater). This happens irrespective of what the key in each array is, and as a result you get a meaningless ordering.

If you wanted to order these arrays by their first key with usort, you would do it like this:

function rcmp($a, $b)
{
    return key($a) - key($b);
}

1 Comment

You're right, I need to use key() in order to compare. Your function doesn't work though =(
0

Here's a solution using create_function that I came up with, accepting the best answer though. Thanks and hope this helps someone else out. $array = array( array(124 => 'foo'), array(123 => 'foo'), // duplicate array(127 => 'foo'), array(126 => 'foo'), array(123 => 'foo'), // duplicate array(125 => 'foo'), );

usort($array, create_function('$a, $b','return (key($a) == key($b)) 
                                                ? 0 
                                                : (key($a) < key($b)) 
                                                   ? -1 
                                                   : 1;'));

print_r($array);

Comments

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.