Эффективная сортировка многомерного массива

#php #arrays #cakephp

#php #массивы #cakephp

Вопрос:

Вот содержимое моего массива:

 array(
  'June 01, 2014' => array(
    (int) 722107 => array(
        'date' => 'June 01, 2014',
        'start_time' => '2:00 AM',
        'end_time' => '03:00 AM'
    ),
    (int) 117646 => array(
        'date' => 'June 01, 2014',
        'start_time' => '12:30 AM',
        'end_time' => '03:30 AM'
    )
  ),
  'May 31, 2014' => array(
    (int) 769349 => array(
        'date' => 'May 31, 2014',
        'start_time' => '12:30 AM',
        'end_time' => '03:30 AM'
    )
  )
)
 

И результат, который я хочу получить, заключается в том, что сначала он должен быть отсортирован по ключам (дата в ASC), а затем снова отсортировать значения каждого ключа по времени начала в ASC.

Основываясь на приведенном выше примере, он должен выводить:

 array(
     'May 31, 2014' => array(
    (int) 769349 => array(
        'date' => 'May 31, 2014',
        'start_time' => '12:30 AM',
        'end_time' => '03:30 AM'
    )
 ),
'June 01, 2014' => array(

    (int) 117646 => array(
        'date' => 'June 01, 2014',
        'start_time' => '12:30 AM',
        'end_time' => '03:30 AM'
    ),
    (int) 722107 => array(
        'date' => 'June 01, 2014',
        'start_time' => '2:00 AM',
        'end_time' => '03:00 AM'
    )
   )

    )
 

Комментарии:

1. Итак, вы хотите отсортировать его по дате?

2. @Darren Да, укажите дату первых ключей, затем, как только она будет отсортирована по ключам. Снова отсортируйте значения каждого ключа на основе start_time, чтобы все было в порядке.

3. Это происходит из базы данных? Если это так, достаточно просто отсортировать его в вашем запросе поиска

4. @scrowler, он поступает не из базы данных, так проще, а из переменной сеанса.

5. Это результат какого-то SQL-запроса? Я понимаю, что вы ищете PHP-решение, но, возможно, вы что-то упустили из виду, например, сортировку в самом SQL-запросе. Опять же: я не знаю, вызывает ли это какое-либо беспокойство, но я просто думаю с вами 😉

Ответ №1:

Два прохода могут быть с uksort() пользовательской функцией и uasort() с использованием пользовательской функции для сравнения двух дат:

 function timeCompare($a, $b)
{
    $va = strtotime($a);
    $vb = strtotime($b);

    if ($va != $vb) {
        return $va < $vb ? -1 : 1;
    }
    return 0;
}

// first pass (sort outer elements)
uksort($data, 'timeCompare');
// second pass (sort inner elements)
foreach ($data as amp;$item) {
    uasort($item, function($a, $b) {
        return timeCompare($a['start_time'], $b['start_time']);
    });
}
 

ДЕМОНСТРАЦИЯ

Комментарии:

1. @zynder Я протестировал его с вашим заданным вводом, и он выдает правильный вывод; пожалуйста, приведите встречный пример (также проверьте добавленную демонстрацию).

2. Да, я сожалею об этом Джеке. Спасибо вам обоим, Джек и @darren.

Ответ №2:

это позволит отсортировать его так, как вы просили.

 $sort = array();
foreach ($d as $key => $item) {
    $sort[$key] = strtotime($key);
}
array_multisort($sort, SORT_ASC, $d);

function sortme($a, $b) {
    return strtotime($a['date']) - strtotime($b['date']);
}

foreach ($d as $k => $i) {
    usort($i, "sortme");
}
 

Который возвращает:

 Array
(
    [May 31, 2014] => Array
        (
            [769349] => Array
                (
                    [date] => May 31, 2014
                    [start_time] => 12:30 AM
                    [end_time] => 03:30 AM
                )

        )

    [June 01, 2014] => Array
        (
            [722107] => Array
                (
                    [date] => June 01, 2014
                    [start_time] => 2:00 AM
                    [end_time] => 03:00 AM
                )

            [117646] => Array
                (
                    [date] => June 01, 2014
                    [start_time] => 12:30 AM
                    [end_time] => 03:30 AM
                )

        )

)
 

Demo


Объяснение

  • В основном первая функция будет сортировать даты May 31, 2014/ June 01, 2014/ ETC .
  • Второй шаг — это foreach цикл, который проходит через дочерние массивы, чтобы отсортировать их по дате / времени.
  • Вуаля, отсортированный массив 🙂

Комментарии:

1. @zynder Извините, да $d , анализируются ли данные (исходный массив)

2. Также в этой части ключа от 1 июня 2014 года первым индексом дочернего массива должен быть 117646, потому что его время начала — 12:30 утра.