0

Given a multidimensional array like this:

$data = array (
[0] => array('aDate' => '2016-01-10', 'tType' => 'Added'),
[1] => array('aDate' => '2016-01-30', 'tType' => 'RtrnCap'),
[2] => array('aDate' => '2016-01-20', 'tType' => 'Removed'),
[3] => array('aDate' => '2016-01-20', 'tType' => 'RtrnCap')
);

How do I sort this array to get this:

$data = array (
[0] => array('aDate' => '2016-01-10', 'tType' => 'Added'),
[1] => array('aDate' => '2016-01-20', 'tType' => 'RtrnCap'),
[2] => array('aDate' => '2016-01-20', 'tType' => 'Removed'),
[3] => array('aDate' => '2016-01-30', 'tType' => 'RtrnCap')
);

Where the sort is first on aDate in ascending order and the second sort is tType custom sorted in the following order: Added, RtrnCap, Removed.

I have searched solutions using multisort like this SO question for "multiple keys" and usort (using an anonymous function) like this SO question to custom sort one key. Each of these is only half of the solution. The TWO sort example uses normal Ascending or Descending sort orders (I need one to be custom order). The custom usort example works fine but its only one set of values.

Bottom line: I need two sorts: the first sort is date ascending, the second one custom.

Community
  • 1
  • 1
globalSchmidt
  • 1,329
  • 16
  • 28
  • @deceze I reviewed the resource that you created. It is comprehensive yet I did not see in it the combination of the two sorts I am attempting to put together. Forgive my newness to the topic, but I need help putting two different sorts together. – globalSchmidt Jun 15 '16 at 13:44
  • Sorting by two criteria at once is covered in the **Sorting by multiple fields** section, sorting in a pre-defined order is covered in **Sorting into a manual, static order**. You simply need to combine these two techniques. Show your best attempt and what specific problem you have in implementing it. – deceze Jun 15 '16 at 13:47

1 Answers1

0
$typeSort = function($a, $b) {
    if ($a['tType'] == $b['tType']) {
        return 0;
    }

    $priority = array('Added' => 0, 'RtrnCap' => 1, 'Removed' => 2);
    return ($priority[$a['tType']] < $priority[$b['tType']]) ? -1 : 1;
};

usort($data, function ($a, $b) use ($typeSort) {
    if ($a['aDate'] == $b['aDate']) {
        return $typeSort($a, $b);
    }

    return ($a['aDate'] < $b['aDate']) ? -1 : 1;
});
Prokhor Sednev
  • 668
  • 7
  • 14
  • Thanks. Can you add some explanation? Looks like even the normal ascending date sort is now a user-defined sort? Also how you might extend this to a third sort, custom or normal. – globalSchmidt Jun 15 '16 at 11:42
  • If we sort by 2 or more columns, we could use only user-defined sort. First we sort by the main column(aDate) - it is an ordinary sort function, but if both values are equal, we must go deeper and sort by second column(tType). If you want to add third column, just replace string `return 0;` in `$typeSort` function with another column sorting function. – Prokhor Sednev Jun 15 '16 at 14:28
  • Perfect. I made two small adjustments to the handling of the positions array. Since this is an externally-sourced array of strings I set `$priority` as follows: `$custom_order_array = array('Added','RtrnCap','Removed', ...); $priority = array_flip($custom_order_array);` Then I moved these two statements outside the typeSort function and set `$typeSort = function ($a,$b) use ($priority);` Works like a charm. – globalSchmidt Jun 15 '16 at 15:31