views:

33

answers:

4

How do you sort a multidimensional array by primary and secondary key? For example, assuming the following array:

$result = array();

$result[0]["prio"] = 1;
$result[0]["date"] = '2010-02-28';
$result[0]["post"] = "February's thoughts";

$result[1]["prio"] = 0;
$result[1]["date"] = '2010-04-20';
$result[1]["post"] = "April's thoughts";

$result[2]["prio"] = 0;
$result[2]["date"] = '2010-05-30';
$result[2]["post"] = "May's thoughts";

I wish to sort the column 'prio' as the primary key (ascending) and 'date' as the secondary key (descending), to obtain:

$result[0]["prio"] = 0;
$result[0]["date"] = '2010-05-30';
$result[0]["post"] = "May's thoughts";
$result[1]["prio"] = 0;
$result[1]["date"] = '2010-04-20';
$result[1]["post"] = "April's thoughts";
$result[2]["prio"] = 1;
$result[2]["date"] = '2010-02-28';
$result[2]["post"] = "February's thoughts";

How to achieve this?

+1  A: 

PHP doesn't have a built-in function to do complex sorting like this, so you'll need to do a usort(), which allows you to sort items using a function that specifies your own criteria.

The example given on the PHP manual page is almost an exact match for what you want to achieve.

http://uk2.php.net/usort

Spudley
Generic sort functions allow to sort on one "column" only......
Riccardo
@Riccardo: usort allows you to specify any criteria to sort by; you can use it to sort on any one or more nested array elements. All you have to do is write a function that returns less than zero or greater than zero depending on which of any of two given elements in your array that you want sorted higher. You can sort on as many 'columns' as you like; you just have to code the function to do it. See @M42's example for proof.
Spudley
A: 

You may use usort() to define custom sort function.
Here's an example

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

$a = array(3, 2, 5, 6, 1);

usort($a, "cmp");

foreach ($a as $key => $value) {
    echo "$key: $value\n";
}
?>

The output will be

0: 1
1: 2
2: 3
3: 5
4: 6

More info can be found at http://www.php.net/manual/en/function.usort.php
It should help you get started.

michal kralik
As I've commented above, those functions allow to sort on one column only....
Riccardo
+1  A: 

array_multisort() should give you the functionality that you need... use Example #3 from the PHP documentation as the basis for your sort, although you'll need to convert those date strings to a datestamp value before executing the sort.

If this data has come from a database query though, it's far easier to sort it within the sql query used to retrieve the information.

Mark Baker
Mark thanks for pointing this out, very useful too!
Riccardo
+3  A: 

Use usort like this:

$result = array();

$result[0]["prio"] = 1;
$result[0]["date"] = '2010-02-28';
$result[0]["post"] = "February's thoughts";

$result[1]["prio"] = 0;
$result[1]["date"] = '2010-04-20';
$result[1]["post"] = "April's thoughts";

$result[2]["prio"] = 0;
$result[2]["date"] = '2010-05-30';
$result[2]["post"] = "May's thoughts";

function fct($a ,$b) {

  if ($a['prio'] < $b['prio']) {
    return -1;
  } elseif  ($a['prio'] > $b['prio']) {
    return 1;
  } else {
    return strcmp($b['date'], $a['date']);
  }

}

usort($result, "fct");
print_r($result);

Output:

Array
(
    [0] => Array
        (
            [prio] => 0
            [date] => 2010-05-30
            [post] => May's thoughts
        )

    [1] => Array
        (
            [prio] => 0
            [date] => 2010-04-20
            [post] => April's thoughts
        )

    [2] => Array
        (
            [prio] => 1
            [date] => 2010-02-28
            [post] => February's thoughts
        )

)
M42
Will this code sort 'date' column within same 'prio' value?
Riccardo
Yes it will, because it compares dates when 'prio' are equal.
M42
Green chechmark coming, let me test one moment!
Riccardo
Yes! Thanks for helping!!!
Riccardo
You're welcome.
M42