【问题标题】:Sorting a 5 dimensional array by date in 5th dimension value using php?使用php按第5维值中的日期对5维数组进行排序?
【发布时间】:2015-09-25 06:08:38
【问题描述】:

我需要使用日期对数组进行排序,但问题是第一个数组将该值存储在键 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
    )

【问题讨论】:

  • 你能发布预期的输出
  • 预期输出是什么?您想要一个仅包含带有字符串值的有序列表的二维数组吗? 你想让数组结构存活下来吗?
  • @ThisName... 不,我想要相同的数组结构,但首先排序最新

标签: php arrays sorting


【解决方案1】:

一般来说,你应该先把数组展平,这样你可以更容易地对它进行排序。 一旦您使用date_addedadded_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);
?> 

【讨论】:

    【解决方案2】:
    • 我们创建了一个函数,该函数将数组作为参数,通过引用传递。
    • 我们也通过引用对其值进行迭代,并将usort 应用于子数组的data 键。
    • usort 查看键 date_addedadded_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
            )
    )
    

    【讨论】:

    • 有趣的解决方案。我会试试看,然后告诉你伙计
    【解决方案3】:

    由于 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
            )
    
    )
    

    使用使用的数组似乎与仅对内部数组进行排序的解决方案没有太大区别。但是,如果您有混合类型的日期,则会有所不同。例如,一个比聊天项目新的媒体项目和另一个更旧的媒体项目。在显示的输出中,所有媒体项都比聊天项更旧。


    感谢 geekonaut 和挥霍。他们的回答启发了我的解决方案:geekonaut's flat solutionspendious's sorting of the inner arrays

    【讨论】:

      【解决方案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());
      

      【讨论】:

      • 我从 db 获取值并将它们推送到数组?你能解释一下我如何在OO方法中做吗?
      • 你能澄清一下吗?这个代码转储可以或不能做这件事,但一些解释会很棒!
      • 所有这些值都来自数据库中的 4 个不同的表,并合并到一个数组中,所以我想根据最新的优先对它们进行排序
      【解决方案5】:

      这有效(对我来说)但会破坏您的数组结构并且您丢失了 [identifier] 键。 我使用 ['id'] 来检查顺序,如果我更改了主题填写的顺序,输出将保持不变(Sorted: Newest first):

      $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();
        }
        

        我不太确定这是否是您想要的,但不管上述函数是合并排序,并且在需要时会派上用场。

        【讨论】:

          猜你喜欢
          • 2011-11-04
          • 2013-11-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-10-31
          • 1970-01-01
          相关资源
          最近更新 更多