Page 1 of 1

multiple sorting

Posted: Sat Sep 03, 2011 4:16 pm
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?

Re: multiple sorting

Posted: Sat Sep 03, 2011 4:27 pm
by Weirdan
array_multisort()

Re: multiple sorting

Posted: Sat Sep 03, 2011 5:05 pm
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>";