Сортировка 5-мерного массива по дате в 5-м измерении с использованием php?

Мне нужно отсортировать массив с использованием дат, но проблема в том, что первый массив сохраняет это значение в ключе added_date, а второй использует ключ date_added.

Как я могу отсортировать их по дате (более новые элементы)?

Массив имеет следующую структуру:

[0] => Array
    (
        [data] => Array
            (
                [0] => Array
                    (
                        [media] => upcomingEvents_1214_1429325758.jpeg
                        [reference] => upcomingEvents
                        [added_date] => 2015-04-18 08:26:00
                        [type] => image/jpeg
                    )

                [1] => Array
                    (
                        [media] => upcomingEvents_1214_1429325809.jpeg
                        [reference] => upcomingEvents
                        [added_date] => 2015-04-18 08:26:51
                        [type] => image/jpeg
                    )

                [2] => Array
                    (
                        [media] => diary_1214_1434190391.jpeg
                        [reference] => diary
                        [added_date] => 2015-06-13 15:43:11
                        [type] => image/jpeg
                    )

            )

        [identifier] => media
    )
 [1] => Array
    (
        [data] => Array
            (
                [0] => Array
                    (
                        [media] => image.jpg
                        [media_thumb] => 
                        [couple_id] => 312
                        [date_added] => 2015-06-22 08:38:09
                        [chat_type] => image/jpeg
                    )

                [1] => Array
                    (
                        [media] => 1432787219556.jpg
                        [media_thumb] => 
                        [couple_id] => 312
                        [date_added] => 2015-06-22 17:45:45
                        [chat_type] => image/jpeg
                    )

                [2] => Array
                    (
                        [media] => 1436160762565.jpg
                        [media_thumb] => 
                        [couple_id] => 312
                        [date_added] => 2015-07-06 09:03:27
                        [chat_type] => image/jpeg
                    )

            )

        [identifier] => chat
    )

Ответ 1

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

Следующий алгоритм выполняет три шага:

  • Deflate массив в двумерный массив
  • Сортировка дефлированного массива
  • Нажать отсортированный массив

Благодарим вас, что мы можем смешивать типы и сортировать их, не теряя структуру.

Код

// Deflate array
function deflate($arr)
{
    $deflated = array();
    foreach($arr as $dataGroup) {
        foreach ($dataGroup['data'] as $item) {
            $item['identifier'] = $dataGroup['identifier'];
            $deflated[] = $item;
        }
    }
    return $deflated;
}

// Inflate array
function inflate($arr)
{
    $inflated = array();
    $lastIdentifier = NULL;

    foreach ($arr as $item) {
        if ($item['identifier'] != $lastIdentifier) {
            if (isset($dataGroup)) {
                $dataGroup['identifier'] = $lastIdentifier;
            }
            unset($dataGroup);
            $dataGroup = array();
            $inflated[] = &$dataGroup;
        }
        $lastIdentifier = $item['identifier'];
        unset($item['identifier']);
        $dataGroup['data'][] = $item;
    }
    if (isset($dataGroup)) {
        $dataGroup['identifier'] = $lastIdentifier;
    }

    return $inflated;
}

// Sort deflated array by date
function sortArray(&$arr)
{
    $callback = function($a, $b)
    {
        if(isset($a['added_date'])) {
            $aDate = $a['added_date'];
        } elseif(isset($a['date_added'])) {
            $aDate = $a['date_added'];
        } else {
            $aDate = '';
        }
        if(isset($b['added_date'])) {
            $bDate = $b['added_date'];
        } elseif(isset($b['date_added'])) {
            $bDate = $b['date_added'];
        } else {
            $bDate = '';
        }
        return ($aDate < $bDate) ? 1 : -1;
    };

    usort($arr, $callback);
}


// Test output

print_r($arr);

// 1. step: deflate array
$arr = deflate($arr);
// echo "--- deflated ---\n";
// print_r($arr);

// 2. step: sort deflated array
sortArray($arr);
// echo "--- deflated and sorted ---\n";
// print_r($arr);

// 3. step: inflate sorted array
$arr = inflate($arr);
echo "--- sorted and inflated ---\n";
print_r($arr);

Вы можете прокомментировать строки печати, чтобы увидеть плоский массив до и после сортировки.

Вывод теста

Array
(
    [0] => Array
        (
            [data] => Array
                (
                    [0] => Array
                        (
                            [media] => upcomingEvents_1214_1429325758.jpeg
                            [reference] => upcomingEvents
                            [added_date] => 2015-04-18 08:26:00
                            [type] => image/jpeg
                        )

                    [1] => Array
                        (
                            [media] => upcomingEvents_1214_1429325809.jpeg
                            [reference] => upcomingEvents
                            [added_date] => 2015-04-18 08:26:51
                            [type] => image/jpeg
                        )

                    [2] => Array
                        (
                            [media] => diary_1214_1434190391.jpeg
                            [reference] => diary
                            [added_date] => 2015-06-13 15:43:11
                            [type] => image/jpeg
                        )

                )

            [identifier] => media
        )

    [1] => Array
        (
            [data] => Array
                (
                    [0] => Array
                        (
                            [media] => image.jpg
                            [media_thumb] => 
                            [couple_id] => 312
                            [date_added] => 2015-06-22 08:38:09
                            [chat_type] => image/jpeg
                        )

                    [1] => Array
                        (
                            [media] => 1432787219556.jpg
                            [media_thumb] => 
                            [couple_id] => 312
                            [date_added] => 2015-06-22 17:45:45
                            [chat_type] => image/jpeg
                        )

                    [2] => Array
                        (
                            [media] => 1436160762565.jpg
                            [media_thumb] => 
                            [couple_id] => 312
                            [date_added] => 2015-07-06 09:03:27
                            [chat_type] => image/jpeg
                        )

                )

            [identifier] => chat
        )

)
--- sorted and inflated ---
Array
(
    [0] => Array
        (
            [data] => Array
                (
                    [0] => Array
                        (
                            [media] => 1436160762565.jpg
                            [media_thumb] => 
                            [couple_id] => 312
                            [date_added] => 2015-07-06 09:03:27
                            [chat_type] => image/jpeg
                        )

                    [1] => Array
                        (
                            [media] => 1432787219556.jpg
                            [media_thumb] => 
                            [couple_id] => 312
                            [date_added] => 2015-06-22 17:45:45
                            [chat_type] => image/jpeg
                        )

                    [2] => Array
                        (
                            [media] => image.jpg
                            [media_thumb] => 
                            [couple_id] => 312
                            [date_added] => 2015-06-22 08:38:09
                            [chat_type] => image/jpeg
                        )

                )

            [identifier] => chat
        )

    [1] => Array
        (
            [data] => Array
                (
                    [0] => Array
                        (
                            [media] => diary_1214_1434190391.jpeg
                            [reference] => diary
                            [added_date] => 2015-06-13 15:43:11
                            [type] => image/jpeg
                        )

                    [1] => Array
                        (
                            [media] => upcomingEvents_1214_1429325809.jpeg
                            [reference] => upcomingEvents
                            [added_date] => 2015-04-18 08:26:51
                            [type] => image/jpeg
                        )

                    [2] => Array
                        (
                            [media] => upcomingEvents_1214_1429325758.jpeg
                            [reference] => upcomingEvents
                            [added_date] => 2015-04-18 08:26:00
                            [type] => image/jpeg
                        )

                )

            [identifier] => media
        )

)

С используемым массивом кажется, что нет большой разницы в решении, которое только сортирует внутренний массив. Но будет разница, если у вас есть даты, которые смешивают типы. Например, элемент мультимедиа, который является новее, чем элемент чата, и другой элемент мультимедиа, который старше. На показанном выходе все элементы мультимедиа старше, чем элементы чата.


Благодаря AVGP и приятным. Они вдохновили меня на мое решение с их ответами: плоское решение AVGP и затратная сортировка внутренних массивов.

Ответ 2

В общем, вы должны сначала сгладить массив, чтобы упростить сортировку. Как только вы получите размерность до разумного плоского массива массивов с помощью date_added или added_date, вы можете использовать usort с функцией, которая проверяет существующий ключ двух, а затем сравнивает их.

Здесь немного упрощенная выборка:

<?php
$arr = array(
  array(
    'data' => array(
      array('date_added' => 3),
      array('date_added' => 1),
      array('date_added' => 6)
    )
  ),
  array(
    'data' => array(
      array('added_date' => 4),
      array('added_date' => 0),
      array('added_date' => 5)
    )
  )
);

function normalize($arr_elem) {
  return $arr_elem['data'];
}

function sort_by_date($a, $b) {
  $dateA = array_key_exists('date_added', $a) ? $a['date_added'] : $a['added_date'];
  $dateB = array_key_exists('date_added', $b) ? $b['date_added'] : $b['added_date'];

  return $dateA > $dateB;
}

$flattened = array_reduce(array_map('normalize', $arr), 'array_merge', array());

usort($flattened, 'sort_by_date');

var_dump($flattened);
?> 

Ответ 3

  • Мы создаем функцию, которая принимает массив как аргумент, передаваемый по ссылке.
  • Мы перебираем его значения также по ссылке и применяем usort к клавише data для подмассивов.
  • usort показывает, доступен ли ключ date_added или added_date, извлекает значения, преобразует их в dateTime и сравнивает их, чтобы вернуть порядок сортировки.

Поскольку вы ничего не говорили о слиянии различных массивов data, это решение сохраняет исходную структуру.

Код

// the function
function sortByDate(&$arr) {

    $callback = function($a, $b) {
        if(isset($a['added_date'])) {
            $key = 'added_date';
        }
        elseif(isset($a['date_added'])) {
            $key = 'date_added';
        }
        else {
            return 0;
        }

        $d1 = DateTime::createFromFormat('Y-m-d H:i:s', $a[$key]);
        $d2 = DateTime::createFromFormat('Y-m-d H:i:s', $b[$key]);

        return ($d1 < $d2) ? 1 : -1;
    };

    foreach($arr as &$subArr) {
        usort($subArr['data'], $callback);
    }
}

Тест

// the data as JSON, provided for reproducibility
$arr = json_decode('[{"data":[
    {"media":"upcomingEvents_1214_1429325758.jpeg","reference":"upcomingEvents","added_date":"2015-04-18 08:26:00","type":"image\/jpeg"},
    {"media":"diary_1214_1434190391.jpeg","reference":"diary","added_date":"2015-06-13 15:43:11","type":"image\/jpeg"},
    {"media":"upcomingEvents_1214_1429325809.jpeg","reference":"upcomingEvents","added_date":"2015-04-18 08:26:51","type":"image\/jpeg"}
],"identifier":"media"},
{"data":[
    {"media":"1432787219556.jpg","media_thumb":"","couple_id":"312","date_added":"2015-06-22 17:45:45","chat_type":"image\/jpeg"},
    {"media":"1436160762565.jpg","media_thumb":"","couple_id":"312","date_added":"2015-07-06 09:03:27","chat_type":"image\/jpeg"},
    {"media":"image.jpg","media_thumb":"","couple_id":"312","date_added":"2015-06-22 08:38:09","chat_type":"image\/jpeg"}
],"identifier":"chat"}]', true);

// testing
print_r($arr);
sortByDate($arr);
echo "--- sorted ---\n";
print_r($arr);

Выход

Array
(
    [0] => Array
        (
            [data] => Array
                (
                    [0] => Array
                        (
                            [media] => upcomingEvents_1214_1429325758.jpeg
                            [reference] => upcomingEvents
                            [added_date] => 2015-04-18 08:26:00
                            [type] => image/jpeg
                        )
                    [1] => Array
                        (
                            [media] => diary_1214_1434190391.jpeg
                            [reference] => diary
                            [added_date] => 2015-06-13 15:43:11
                            [type] => image/jpeg
                        )
                    [2] => Array
                        (
                            [media] => upcomingEvents_1214_1429325809.jpeg
                            [reference] => upcomingEvents
                            [added_date] => 2015-04-18 08:26:51
                            [type] => image/jpeg
                        )
                )
            [identifier] => media
        )
    [1] => Array
        (
            [data] => Array
                (
                    [0] => Array
                        (
                            [media] => 1432787219556.jpg
                            [media_thumb] =>
                            [couple_id] => 312
                            [date_added] => 2015-06-22 17:45:45
                            [chat_type] => image/jpeg
                        )

                    [1] => Array
                        (
                            [media] => 1436160762565.jpg
                            [media_thumb] =>
                            [couple_id] => 312
                            [date_added] => 2015-07-06 09:03:27
                            [chat_type] => image/jpeg
                        )
                    [2] => Array
                        (
                            [media] => image.jpg
                            [media_thumb] =>
                            [couple_id] => 312
                            [date_added] => 2015-06-22 08:38:09
                            [chat_type] => image/jpeg
                        )
                )
            [identifier] => chat
        )
)
--- sorted ---
Array
(
    [0] => Array
        (
            [data] => Array
                (
                    [0] => Array
                        (
                            [media] => diary_1214_1434190391.jpeg
                            [reference] => diary
                            [added_date] => 2015-06-13 15:43:11
                            [type] => image/jpeg
                        )
                    [1] => Array
                        (
                            [media] => upcomingEvents_1214_1429325809.jpeg
                            [reference] => upcomingEvents
                            [added_date] => 2015-04-18 08:26:51
                            [type] => image/jpeg
                        )
                    [2] => Array
                        (
                            [media] => upcomingEvents_1214_1429325758.jpeg
                            [reference] => upcomingEvents
                            [added_date] => 2015-04-18 08:26:00
                            [type] => image/jpeg
                        )
                )
            [identifier] => media
        )
    [1] => Array
        (
            [data] => Array
                (
                    [0] => Array
                        (
                            [media] => 1436160762565.jpg
                            [media_thumb] =>
                            [couple_id] => 312
                            [date_added] => 2015-07-06 09:03:27
                            [chat_type] => image/jpeg
                        )
                    [1] => Array
                        (
                            [media] => 1432787219556.jpg
                            [media_thumb] =>
                            [couple_id] => 312
                            [date_added] => 2015-06-22 17:45:45
                            [chat_type] => image/jpeg
                        )
                    [2] => Array
                        (
                            [media] => image.jpg
                            [media_thumb] =>
                            [couple_id] => 312
                            [date_added] => 2015-06-22 08:38:09
                            [chat_type] => image/jpeg
                        )
                )
            [identifier] => chat
        )
)

Ответ 4

Лично я предпочитаю OO-подход:)

<?php
date_default_timezone_set('Europe/London');

class ArraySort {
    private $unsortedArray          = array();
    private $sortedArray            = array();
    private static $dateKeySynonym  = array('added_date', 'date_added');

    public function __construct($unsortedArray) {
        $this->unsortedArray = $unsortedArray;
    }

    public function doSort() {
        $outputArray = array();
        foreach ($this->unsortedArray as $cell) {
            $identifier = $cell['identifier'];
            foreach ($cell['data'] as $subCell) {
                // must keep the identifier : don't loose it !!
                $subCell['identifier']  = $identifier;
                $outputArray[]          = $subCell;
            }
        }
        usort($outputArray, array('ArraySort', '_sort'));
        $this->sortedArray = $outputArray;
    }

    public function getSortedArray() {
        return $this->sortedArray;
    }

    private static function _sort($a, $b) {
        $date1 = NULL;
        $date2 = NULL;

        foreach(self::$dateKeySynonym as $dateKeySynonym) {
            if (isset($a[$dateKeySynonym])) {
                $date1 = new DateTime($a[$dateKeySynonym]);
                break;
            }
        }

        foreach(self::$dateKeySynonym as $dateKeySynonym) {
            if (isset($b[$dateKeySynonym])) {
                $date2 = new DateTime($b[$dateKeySynonym]);
                break;
            }
        }

        return ($date1 < $date2);
    }
}

// ---------------------- test class ---------------------------
$a[0]['identifier'] = 'media';

$cell['media']      = 'upcomingEvents_1214_1429325758.jpeg';
$cell['reference']  = 'upcomingEvents';
$cell['added_date'] = '2015-04-18 08:26:00';
$cell['type']       = 'image/jpeg';
$a[0]['data'][]     = $cell;

$cell['media']      = 'upcomingEvents_1214_1429325809.jpeg';
$cell['reference']  = 'upcomingEvents';
$cell['added_date'] = '2015-04-18 08:25:51';
$cell['type']       = 'image/jpeg';
$a[0]['data'][]     = $cell;

$cell['media']      = 'diary_1214_1434190391.jpeg';
$cell['reference']  = 'diary';
$cell['added_date'] = '2015-06-13 15:43:11';
$cell['type']       = 'image/jpeg';
$a[0]['data'][]     = $cell;

// -----------------------------------------------------------
unset($cell);
// -----------------------------------------------------------

$a[1]['identifier']     = 'chat';

$cell['media']          = 'image.jpg';
$cell['media_thumb']    = ''; 
$cell['couple_id']      = 312;
$cell['date_added']     = '2015-06-22 08:38:09';
$cell['chat_type']      = 'image/jpeg';
$a[1]['data'][]         = $cell;

$cell['media']          = '1436160762565.jpg';
$cell['media_thumb']    = ''; 
$cell['couple_id']      = 312;
$cell['date_added']     = '2015-07-06 09:03:27';
$cell['chat_type']      = 'image/jpeg';
$a[1]['data'][]         = $cell;

// -------------------------------------------------------------

$arraySort = new ArraySort($a);
$arraySort->doSort();
var_dump($arraySort->getSortedArray());

Ответ 5

Это работает (для меня), но разрушает структуру массива, и вы теряете ключ [identifier]. Я использовал ['id'], чтобы проверить порядок, если я изменил порядок, в котором объект заполнен, выход останется неизменным (Отсортировано: сначала самое новое):

$subject = array(
    array( 'data' => array(
            array( 'id' => 1 , 'added_date' => '2015-04-18 08:26:00' ) ,
            array( 'id' => 2 , 'added_date' => '2015-04-18 08:26:51' ) ,
            array( 'id' => 3 , 'added_date' => '2015-06-13 15:43:11' ) ,
    ) ) ,
    array( 'data' => array(
        array( 'id' => 4 , 'date_added' => '2015-06-22 08:38:09' ) ,
        array( 'id' => 5 , 'date_added' => '2015-06-22 17:45:45' ) ,
        array( 'id' => 6 , 'date_added' => '2015-07-06 09:03:27' ) ,
    ) ) );
$dates = array();
foreach ($subject as $k1=>$d1) {
    foreach ($d1['data'] as $k3=>$d3) {
        if(isset($d3['date_added'])) array_push($dates, $d3['date_added'].'|'.$k1.'|'.$k3);
        if(isset($d3['added_date'])) array_push($dates, $d3['added_date'].'|'.$k1.'|'.$k3);
    }

}
rsort($dates, SORT_STRING );
$sorted = array();
foreach ($dates as $val) {
    preg_match('/([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9])\|([0-9]+)\|([0-9]+)/',$val, $matches);
    array_push($sorted, $subject[$matches[2]]['data'][$matches[3]]);
}
$result= array();
foreach ($sorted as $key => $val) {
    $result[(count($sorted)-1)-$key]=$val;
}
print_r($result); // < This prints the array

Если это решение не подходит для вас, прокомментируйте и я попытаюсь настроить.

Ответ 6

Как указывали другие, я не уверен, какой результат вы ожидаете. Массив, приведенный здесь, представляет собой массив элементов мультимедиа, отсортированных по датам. Они находятся в одном формате, только теперь это всего лишь двумерный массив. Он использует сортировку слияния для сортировки элементов массива. Я не тестировал этот код, но этого достаточно для того, что вам нужно. Мы используем класс Splqueue для сортировки элементов:

$searchQueue = new SplQueue(); // we will store our media nodes here
$sortedQueue = new SplQueue(); // we will have our sorted array nodes here

Наша первая функция найдет элементы мультимедиа и поместит их в очередь

function findArrays($someArray) {
    foreach ($someArray as $anArray) {
        if (array_key_exists("type", $anArray) {
            // bottom level array
            $searchQueue.enqueue($anArray);
        }
        else {
            $searchQueue.enqueue(sortArrays($anArray));
        }
    }
}

Эта следующая функция будет гранулировать эти элементы мультимедиа и является рекурсивной. Как только он гранулируется до одной ячейки, функция начинает сортировку через нашу следующую функцию...

function mergeSort($someQueue){
    if ($someQueue.count() <= 1 {
        return $someQueue;
    }
    $left = new SplQueue();
    $right = new SplQueue();
    $middle = (int)$someQueue.count() / 2;
    for ($x = 0; $x < $middle; $x++){
        $left.queue($someQueue.dequeue());
    }
    for ($x = 0; $x < $someQueue.count(); $x++){
        $right.queue($someQueue.dequeue());
    }
    $sortedLeft = mergeSort($left);
    $sortedRight = mergeSort($right);
    return merge($sortedLeft, $sortedRight); // calls the sorting function
}

Последняя функция - это то, что фактически сортирует элементы. Это займет две очереди и сравните их значения.

function merge($left, $right){
    $result = new SplQueue();
    $dateTimeFormat = "Y-m-d H:i:s";
    while (!$left.isEmpty() && !$right.isEmpty()) {
        // find what we are going to compare to what (added_date or date_added)
        $leftVal;
        $rightVal;
        if (array_key_exists("added_date", $left.bottom())) {
            $leftVal = DateTime::createFromFormat($dateTimeFormat, $left.bottom()["added_date"]);
        }
        else {
            $leftVal = DateTime::createFromFormat($dateTimeFormat, $left.bottom()["date_added"]);
        }
        if (array_key_exists("added_date", $right.bottom())) {
            $rightVal = DateTime::createFromFormat($dateTimeFormat, $right.bottom()["added_date"]);
        }
        else {
            $rightVal = DateTime::createFromFormat($dateTimeFormat, $right.bottom()["date_added"]);
        }

        // $leftVal and $rightVal now contain the values we are going to compare
        if ($leftVal < $rightVal) {
            $result.enqueue($left.dequeue());
        }
        else {
            $result.enqueue($right.dequeue());
        }
    }
    while (!$left.isEmpty()) {
        $result.enqueue($left.dequeue());
    }
    while (!$left.isEmpty()) {
        $result.enqueue($right.dequeue());
    }
    return $result;
}

Эти две функции используются вместе с определенными очередями для создания сортированной очереди. Затем очередь помещается в массив.

// bread and butter
findArrays($yourArrays);
$sortedMediaNodes = mergeSort($searchQueue); // sorted media nodes in a queue
$arrayResults = array(); // will contain an array of the $sortedMediaNodes queue
while (!$sortedMediaNodes.isEmpty()) {
    $arrayResults[] = $sortedMediaNodes.dequeue();
}

Я не совсем уверен, что это то, что вы хотели, но независимо от того, какие вышеперечисленные функции являются сортировкой слияния и при необходимости при необходимости.