up vote 1 down vote favorite

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?

link|flag

1  
Does this data originate from a database? Perhaps you could retrieve the data in correct order by modifying your original query. – nnevala Oct 19 at 13:04
Not enough data from DB to achieve this :-( – Riccardo Oct 19 at 13:16

4 Answers

up vote 3 down vote accepted

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
        )

)
link|flag
Will this code sort 'date' column within same 'prio' value? – Riccardo Oct 19 at 13:52
Yes it will, because it compares dates when 'prio' are equal. – M42 Oct 19 at 13:54
Green chechmark coming, let me test one moment! – Riccardo Oct 19 at 13:57
Yes! Thanks for helping!!! – Riccardo Oct 19 at 14:10
You're welcome. – M42 Oct 19 at 14:13
up vote 1 down vote

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

link|flag
Generic sort functions allow to sort on one "column" only...... – Riccardo Oct 19 at 13:17
@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 Oct 19 at 13:52
up vote 1 down vote

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.

link|flag
Mark thanks for pointing this out, very useful too! – Riccardo Oct 19 at 14:12
up vote 0 down vote

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.

link|flag
As I've commented above, those functions allow to sort on one column only.... – Riccardo Oct 19 at 13:18

Your Answer

 
or
never shown

Not the answer you're looking for? Browse other questions tagged or ask your own question.