multiple sorting

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
Eric!
DevNet Resident
Posts: 1146
Joined: Sun Jun 14, 2009 3:13 pm

multiple sorting

Post by Eric! »

I was just playing around with some code and I started to wonder what would be a good way to perform multiple sorts on multi-dimensional arrays like spreadsheets can perform (sort by X then sort by Y, then sort by Z...). And I can't figure out a good generic method.

For example I have the following code that can sort by one element:

Code: Select all

$people = array(
    '0' => array('loc' => 'DC', 'job' => 'Driver', 'pay' => '20'),
    '1' => array('loc' => 'LA', 'job' => 'Chef', 'pay' => '40'),
    '2' => array('loc' => 'NY', 'job' => 'Fire Eater', 'pay' => '100'),
    '3' => array('loc' => 'LA', 'job' => 'Boss', 'pay' => '55'),
    '4' => array('loc' => 'NY', 'job' => 'Drunkard', 'pay' => '44'),
    '5' => array('loc' => 'NY', 'job' => 'Thief', 'pay' => '55')
);

echo "<html><pre>";
echo sort_array($people, "pay");
echo"</pre></html>";

function sort_array($array, $key) {
    $keys = array();
    for ($i = 1; $i < func_num_args(); $i++) {
        $keys[$i - 1] = func_get_arg($i);
    }
    // anon function
    $func = function ($a, $b) use ($keys) {
                for ($i = 0; $i < count($keys); $i++) {
                    if ($a[$keys[$i]] != $b[$keys[$i]]) {
                        return ($a[$keys[$i]] > $b[$keys[$i]]) ? -1 : 1;
                    }
                }
                return 0;
            };

    usort($array, $func);
    return $array;
}
But what if I want is to sort by 'pay' and then by 'loc' as a second sort that respects the previous sort's groupings, something like:
'2' => array('loc' => 'NY', 'job' => 'Fire Eater', 'pay' => '100')
'5' => array('loc' => 'NY', 'job' => 'Thief', 'pay' => '55')
'4' => array('loc' => 'NY', 'job' => 'Drunkard', 'pay' => '44')
'3' => array('loc' => 'LA', 'job' => 'Boss', 'pay' => '55')
'1' => array('loc' => 'LA', 'job' => 'Chef', 'pay' => '40')
'0' => array('loc' => 'DC', 'job' => 'Driver', 'pay' => '20')

Any ideas?
User avatar
Weirdan
Moderator
Posts: 5978
Joined: Mon Nov 03, 2003 6:13 pm
Location: Odessa, Ukraine

Re: multiple sorting

Post by Weirdan »

array_multisort()
Eric!
DevNet Resident
Posts: 1146
Joined: Sun Jun 14, 2009 3:13 pm

Re: multiple sorting

Post by Eric! »

Yeah that's pretty much what I'm trying to figure out how it works. After playing with it a bit, I guess the idea is if the data is broken into columns, sorted with additional information on where the original key location is in the primary array, then after the columns are sorted in whatever fashion, the original array with it's data is then rebuilt.

Code: Select all

$people = array(
    '0' => array('loc' => 'DC', 'job' => 'Driver', 'pay' => '20'),
    '1' => array('loc' => 'LA', 'job' => 'Chef', 'pay' => '40'),
    '2' => array('loc' => 'NY', 'job' => 'Fire Eater', 'pay' => '100'),
    '3' => array('loc' => 'LA', 'job' => 'Boss', 'pay' => '55'),
    '4' => array('loc' => 'NY', 'job' => 'Drunkard', 'pay' => '44'),
    '5' => array('loc' => 'NY', 'job' => 'Thief', 'pay' => '55')
);
// Obtain a list of columns
foreach ($people as $key => $row) {
    $loc[$key]  = $row['loc'];
    $job[$key] = $row['job'];
    $pay[$key] = $row['pay'];
}
array_multisort($loc, SORT_ASC, $pay, SORT_DESC, $people);
echo "<html><pre>";
var_dump($people);
echo"</pre></html>";
Post Reply