6

I need to sort the notification array by the value 'start_date' DESC order from the getNotifications function:

$posts_id_arr = getPoststIds($conn);

foreach ($posts_id_arr as $key => $val) {
  $total_arr[$key] = [
    'notification' => getNotifications($val['post_id'], $user_id, $conn)
  ];
}

$response_array = array('data' => $total_arr, 'more things' => $more_array);
echo json_encode($response_array);

right now the order is by post id due to the foreach loop.

data {
       notification: 
      [
       {
        post_id: “1",
        start_date: "2016-10-10 08:00:00",
       },
       {
        post_id: “1",
        start_date: "2016-10-10 12:00:00",
       }
    ],
     notification:
      [
        post_id: “2",
        start_date: "2016-10-10 09:00:00",
       },
       {
        post_id: “2",
        start_date: "2016-10-10 13:00:00",
       }
    ]
}

And i need it to be 1: 08:00, 2: 09:00, 1: 12:00, 2: 13:00

Gilad Adar
  • 193
  • 1
  • 5
  • 11
  • I think you should sort the data after the loop, that would be helpful and takes less iteration. – Aman Garg Oct 10 '16 at 07:16
  • Possible duplicate of [PHP Sort Array By SubArray Value](http://stackoverflow.com/questions/2477496/php-sort-array-by-subarray-value) – Epodax Oct 10 '16 at 07:16
  • @Gilad Adar. Have you tried with my solutions. If not try and share thought and if you face any hindrance let me know so that we shall rectify it. – Naresh Kumar P Oct 10 '16 at 08:41

5 Answers5

2

You can use a custom function to sort the values in the array using uasort. Your date format is sortable using strcmp - a date in the past is lower than a date in the future, so you can use this in your comparator.

function sort_by_date($a, $b) {
  return strcmp($a->start_date, $b->start_date);
}

$sorted_posts = uasort($total_arr->notification, 'sort_by_date');

$response_array = array('data' => $sorted_posts, 'more things' => $more_array);
clinton3141
  • 4,751
  • 3
  • 33
  • 46
0

If you want to sort with the inner array you can better prefer for the usort() method.

usort — Sort an array by values using a user-defined comparison function

This function will sort an array by its values using a user-supplied comparison function. If the array you wish to sort needs to be sorted by some non-trivial criteria, you should use this function.

<?php
function cmp($a, $b)
{
    return strcmp($a["fruit"], $b["fruit"]);
}

$fruits[0]["fruit"] = "lemons";
$fruits[1]["fruit"] = "apples";
$fruits[2]["fruit"] = "grapes";

usort($fruits, "cmp");

while (list($key, $value) = each($fruits)) {
    echo "\$fruits[$key]: " . $value["fruit"] . "\n";
}
?>

When sorting a multi-dimensional array, $a and $b contain references to the first index of the array.

The above example will output:

$fruits[0]: apples
$fruits[1]: grapes
$fruits[2]: lemons

Alternative Solution:

You can try array_multisort() since it will sort the array based on the order that you need.

$arr  = your array;
$sort = array();
foreach($arr as $k=>$v) {
    $sort['field'][$k] = $v['field'];
}

array_multisort($sort['field'], SORT_DESC, $arr);

echo "<pre>";
print_r($arr);
Naresh Kumar P
  • 4,127
  • 2
  • 16
  • 33
  • the "fruits" (posts_id_arr) is not the issue, i need to sort the total_arr – Gilad Adar Oct 10 '16 at 07:11
  • I think He need to sort the full array, And that could be applicable only after the for loop. – Aman Garg Oct 10 '16 at 07:14
  • ya if he is Trying to sort the full array. He can sort using `ksort` right. But if he is trying to sort the inner array alone he can do `array_multisort()` But it is advisable to get the output and then sort in the order he wants right. – Naresh Kumar P Oct 10 '16 at 07:17
0

However, you don't need to perform the sort inside the foreach.

You can try the below code. Change the variable name accordingly.

foreach ($points as $key => $val) {
    $time[$key] = $val[0];
}

array_multisort($time, SORT_ASC, $points);

This is because of the way array_multisort works. It sorts multiple arrays, and when the $time array is sorted, the $points array is re-ordered according to the array indices in $time. The array_multisort should come after the foreach, though
Hope this would be helpful.

Aman Garg
  • 3,122
  • 4
  • 24
  • 32
0

You can follow these steps:

1) Define a temporary array to store the dates:

foreach ($total_arr['notification'] as $vals) {
    $temp_dates[] = $vals['start_date'];
}

2) Sort the newly created temp array using arsort():

arsort($temp_dates);

3) Use array_filter() and loop to find corresponding post ids and store to resulting array:

$i = 0;
foreach ($total_arr['notification'] as $vals) {
    $res['notification'][] = array_filter($vals, function($val) {
        return $val['start_date'] == $temp_dates[$i];
    });
    $i++;
}

$response_array = array('data' => $res, 'more things' => $more_array);

Note: Not sure if it works with duplicate start_dates.

Rax Weber
  • 3,730
  • 19
  • 30
0

As iblamefish mentioned, using uasort() is the way to go - it is simple an both memory and processing efficient, compared to all the other answers. But while strcmp() does produce good results for the SQL-style dates that you have, it is not the "correct" way to handle time fields - you should parse the times and compare them as time values:

$a = [
  [ "name" => "foo", "date" => "2016-08-09 10:30:00" ],
  [ "name" => "bar", "date" => "2016-01-09 02:00:00" ],
  [ "name" => "baz", "date" => "2016-11-02 18:21:34" ]
];
uasort($a, function($a,$b) {
  return (new DateTime($a->date))->getTimestamp() - (new DateTime($b->date))->getTimestamp();
});
var_dump($a);

produces:

array(3) {
  [0] =>
  array(2) {
    'name' =>
    string(3) "foo"
    'date' =>
    string(19) "2016-08-09 10:30:00"
  }
  [1] =>
  array(2) {
    'name' =>
    string(3) "bar"
    'date' =>
    string(19) "2016-01-09 02:00:00"
  }
  [2] =>
  array(2) {
    'name' =>
    string(3) "baz"
    'date' =>
    string(19) "2016-11-02 18:21:34"
  }
}

Also, closures (anonymous functions) are more fun than using old-style "text callables").

Guss
  • 30,470
  • 17
  • 104
  • 128