Сортировка трехмерного массива на 2-м уровне по значениям 3-го уровня

Я использую Google Calendar API для извлечения данных из нескольких календарей. Я создаю массив, чтобы я мог отформатировать отображение данных. У меня проблемы с сортировкой данных, чтобы события отображались в правильном порядке.

Мой основной вид включен datetime ASC. Если два даты совпадают, я хочу отсортировать alldayflag DESC. Я только хочу, чтобы это сортировалось в пределах каждой даты.

Вот образец моих данных:

Array
(
[2016-01-29] => Array
(
[0] => Array
(
[date] => January 29
[time] => 8:30 am
[datetime] => 2016-01-29T08:30:00-06:00
[alldayflag] => 0
)
[1] => Array
(
[date] => January 29
[time] => 12:00 am
[datetime] => 2016-01-29T00:00:00-06:00
[alldayflag] => 1
)
[2] => Array
(
[date] => January 29
[time] => 2:00 pm
[datetime] => 2016-01-29T14:00:00-06:00
[alldayflag] => 0
)
[3] => Array
(
[date] => January 29
[time] => 10:00 am
[datetime] => 2016-01-29T10:00:00-06:00
[alldayflag] => 0
)
[4] => Array
(
[date] => January 29
[time] => 12:00 pm
[datetime] => 2016-01-29T12:00:00-06:00
[alldayflag] => 0
)
)
[2016-01-30] => Array
(
[0] => Array
(
[date] => January 30
[time] => 4:00 pm
[datetime] => 2016-01-30T16:00:00-06:00
[alldayflag] => 0
)
[1] => Array
(
[date] => January 30
[time] => 5:00 pm
[datetime] => 2016-01-30T17:00:00-06:00
[alldayflag] => 0
)
[2] => Array
(
[date] => January 30
[time] => 11:00 am
[datetime] => 2016-01-30T11:00:00-06:00
[alldayflag] => 0
)
)
)

Я пытался использовать array_multisort(), Я получаю правильные результаты сортировки, однако я также получаю сообщение об ошибке:

Предупреждение: array_multisort (): размеры массива несовместимы в файле sort-array.php в строке XXX

$getBeginDate = '2016-01-29';
$getEndDate = '2016-01-31';

$getCurrentDate = $getBeginDate;

while(strtotime($getCurrentDate) < strtotime($getEndDate)) {

foreach ($list[$getCurrentDate] as $key => $row){
$datetime[$key] = $row['datetime'];
$alldayflag[$key] = $row['alldayflag'];
}

array_multisort($datetime, SORT_ASC, $alldayflag, SORT_DESC, $list[$getCurrentDate]);

$getCurrentDate = date('Y-m-d', strtotime($getCurrentDate . " +1 day"));

}

Я также пытался uasort(), Это не сортирует должным образом вообще.

uasort($list, 'sortCriteria');

function sortCriteria($array, $key) {
if(strtotime($a['datetime']) == strtotime($b['datetime'])) {
if($a['allday'] < $b['allday']) {
return -1;
} else {
return 0;
}
}

return (strtotime($a['datetime']) < strtotime($b['datetime'])) ? -1 : 1;

}

Любая помощь с благодарностью.

0

Решение

array_multisort это определенно путь, по которому вы хотите идти. У меня есть непроверенный ответ для вас, поэтому я могу быть поражен гневом сообщества, если это неверное предположение, но похоже, что вы столкнулись с проблемой закрытия или, скорее, с ее отсутствием. Это должно исправить вашу проблему:

...
while(strtotime($getCurrentDate) < strtotime($getEndDate)) {

$datetime = [];
$alldayflag = [];
foreach ($list[$getCurrentDate] as $key => $row){
...

Мое предположение из ошибки, которую вы упомянули, заключается в том, что если вы сбросили $datetime перед мультисортикой в ​​нем будет 5 элементов в первый раз и 5 элементов во второй раз.

first_dump => '29th', '29th', '29th', '29th', '29th'
second_dump => '30th', '30th', '30th', '29th', '29th'

Или что-то похожее на это. Происходит следующее: $ datetime сохраняется во время первого раунда цикла while во второй раз. Который взрывает ваш мультисорт во второй раз, потому что есть только 3 предмета, а не 5.

Я надеюсь, что в этом есть смысл.

0

Другие решения

Возможным решением может быть использование usort.
Затем вы можете использовать DateTime сравнить дату и время.
Тогда, если два datetime равны, вы можете сравнить «alldayflag».

Например:

function sortCriteria($a, $b)
{
$aDateTime = new DateTime($a['datetime']);
$bDateTime = new DateTime($b['datetime']);

if ($aDateTime == $bDateTime) {
return ($a['alldayflag'] > $b['alldayflag']) ? -1 : 1;
}

return ($aDateTime < $bDateTime) ? -1 : 1;
}

$getBeginDate = '2016-01-29';
$getEndDate = '2016-01-31';
$getCurrentDate = $getBeginDate;

while(strtotime($getCurrentDate) < strtotime($getEndDate)) {
usort($list[$getCurrentDate], 'sortCriteria');
$getCurrentDate = date('Y-m-d', strtotime($getCurrentDate . " +1 day"));
}

демонстрация

0