PHP按包含日期的元素对多维数组进行排序

PHP按包含日期的元素对多维数组进行排序,php,datetime,arrays,sorting,Php,Datetime,Arrays,Sorting,我有一个数组,例如: Array ( [0] => Array ( [id] => 2 [type] => comment [text] => hey [datetime] => 2010-05-15 11:29:45 ) [1] => Array ( [id] => 3 [type] => status [te

我有一个数组,例如:

Array
(
[0] => Array
    (
        [id] => 2
        [type] => comment
        [text] => hey
        [datetime] => 2010-05-15 11:29:45
    )

[1] => Array
    (
        [id] => 3
        [type] => status
        [text] => oi
        [datetime] => 2010-05-26 15:59:53
    )

[2] => Array
    (
        [id] => 4
        [type] => status
        [text] => yeww
        [datetime] => 2010-05-26 16:04:24
    )

)
有人能建议一种基于datetime元素对其进行排序/排序的方法吗?

使用和自定义比较函数:

function date_compare($a, $b)
{
    $t1 = strtotime($a['datetime']);
    $t2 = strtotime($b['datetime']);
    return $t1 - $t2;
}    
usort($array, 'date_compare');

编辑:您的数据以数组的形式组织。为了更好地区分这些,让我们调用内部数组(数据)记录,以便您的数据实际上是一个记录数组

usort
将一次将其中两条记录传递给给定的比较函数
date\u compare()
date\u compare
然后将每条记录的
“datetime”
字段提取为UNIX时间戳(整数),并返回差值,这样,如果两个日期相等,结果将为
0
;如果第一个(
$a
)较大,则为正数;如果第二个参数(
$b
),则为负值更大
usort()
使用此信息对数组进行排序。

见第三个例子:

<?php

$data[] = array('volume' => 67, 'edition' => 2);
$data[] = array('volume' => 86, 'edition' => 1);
$data[] = array('volume' => 85, 'edition' => 6);
$data[] = array('volume' => 98, 'edition' => 2);
$data[] = array('volume' => 86, 'edition' => 6);
$data[] = array('volume' => 67, 'edition' => 7);

foreach ($data as $key => $row) {
    $volume[$key]  = $row['volume'];
    $edition[$key] = $row['edition'];
}

array_multisort($volume, SORT_DESC, $edition, SORT_ASC, $data);

?>


仅供参考,使用unix(1970年起的秒数)或mysql时间戳(YmdHis-20100526014500)对解析器来说会更容易,但我认为在您的情况下,这没有什么区别。

按指定的mysql日期时间字段和顺序对记录数组/assoc_数组进行排序:

function build_sorter($key, $dir='ASC') {
    return function ($a, $b) use ($key, $dir) {
        $t1 = strtotime(is_array($a) ? $a[$key] : $a->$key);
        $t2 = strtotime(is_array($b) ? $b[$key] : $b->$key);
        if ($t1 == $t2) return 0;
        return (strtoupper($dir) == 'ASC' ? ($t1 < $t2) : ($t1 > $t2)) ? -1 : 1;
    };
}


// $sort - key or property name 
// $dir - ASC/DESC sort order or empty
usort($arr, build_sorter($sort, $dir));
功能构建\分拣机($key,$dir='ASC')){
返回函数($a,$b)使用($key,$dir){
$t1=strotime(is_数组($a)?$a[$key]:$a->$key);
$t2=strotime(is_数组($b)?$b[$key]:$b->$key);
如果($t1=$t2)返回0;
返回(strtoupper($dir)=‘ASC’?($t1<$t2):($t1>$t2))?-1:1;
};
}
//$sort-键或属性名称
//$dir-ASC/DESC排序顺序或为空
usort($arr,build_sorter($sort,$dir));

这应该行得通。我通过strotime将日期转换为unix时间

  foreach ($originalArray as $key => $part) {
       $sort[$key] = strtotime($part['datetime']);
  }
  array_multisort($sort, SORT_DESC, $originalArray);

一个线性版本将使用多个数组方法:

array_multisort(array_map('strtotime',array_column($originalArray,'datetime')),
                SORT_DESC, 
                $originalArray);

我无意中看到了这篇文章,但我想在返回类中的项目时按时间排序,结果出现了一个错误

因此,我研究了php.net网站,并最终做了以下工作:

class MyClass {
   public function getItems(){
      usort( $this->items, array("MyClass", "sortByTime") );
      return $this->items;
   }
   public function sortByTime($a, $b){
      return $b["time"] - $a["time"];
   }
}
您可以在中找到非常有用的示例

我的数组如下所示:

  'recent' => 
    array
      92 => 
        array
          'id' => string '92' (length=2)
          'quantity' => string '1' (length=1)
          'time' => string '1396514041' (length=10)
      52 => 
        array
          'id' => string '52' (length=2)
          'quantity' => string '8' (length=1)
          'time' => string '1396514838' (length=10)
      22 => 
        array
          'id' => string '22' (length=2)
          'quantity' => string '1' (length=1)
          'time' => string '1396514871' (length=10)
      81 => 
        array
          'id' => string '81' (length=2)
          'quantity' => string '2' (length=1)
          'time' => string '1396514988' (length=10)

您可以使用with回调函数简单地解决这个问题。无需编写任何自定义函数

$your_date_field_name = 'datetime';
usort($your_given_array_name, function ($a, $b) use (&$your_date_field_name) {
    return strtotime($a[$your_date_field_name]) - strtotime($b[$your_date_field_name]);
});
在php7中,您可以使用:

usort($array,function($a,$b){
返回新的日期时间($a['DateTime'])新的日期时间($b['DateTime']);
});

对于
'd/m/Y'
日期:

usort($array, function ($a, $b, $i = 'datetime') { 
    $t1 = strtotime(str_replace('/', '-', $a[$i]));
    $t2 = strtotime(str_replace('/', '-', $b[$i]));

    return $t1 > $t2;
});

其中,
$i
是数组索引

对于那些仍在使用函数sortByDate的类中以这种方式求解它的人,请参见下面的代码

<?php

class ContactsController 
{
    public function __construct()
    {
    //
    }


    function sortByDate($key)
    {
        return function ($a, $b) use ($key) {
            $t1 = strtotime($a[$key]);
            $t2 = strtotime($b[$key]);
            return $t2-$t1;
        };

    }

    public function index()
    {

        $data[] = array('contact' => '434343434', 'name' => 'dickson','updated_at' =>'2020-06-11 12:38:23','created_at' =>'2020-06-11 12:38:23');
        $data[] = array('contact' => '434343434', 'name' => 'dickson','updated_at' =>'2020-06-16 12:38:23','created_at' =>'2020-06-10 12:38:23');
        $data[] = array('contact' => '434343434', 'name' => 'dickson','updated_at' =>'2020-06-7 12:38:23','created_at' =>'2020-06-9 12:38:23');


        usort($data, $this->sortByDate('updated_at'));

        //usort($data, $this->sortByDate('created_at'));
        echo $data;

    }
}

以前的大多数答案都没有确认将日期时间值作为简单字符串进行比较的可用快捷方式。其他认识到strotime()不必要的答案并没有说明他们为什么这么做……所以我会的

因为您的
datetime
值是用降序单位(
Y
m
d
H
i
s
)格式化的,而且因为每个单位都用相同数量的字符(4,2,2,2,2)表示由于分隔字符在不同的字符串中都是相同的,所以您可以简单地从左到右(自然地)逐字符比较它们。对于格式化为(比如)d/m/Y
的日期字符串来说,这是不正确的

有两个函数非常适合此任务,我将演示这两个函数的ASC和DESC版本

  • usort()按日期列描述:

    usort($array, function($a, $b) { return $b['datetime'] <=> $a['datetime']; });
    
     array_multisort(array_column($array, 'datetime'), SORT_DESC, $array);
    
  • 数组_multisort()按日期列ASC:

    usort($array, function($a, $b) { return $a['datetime'] <=> $b['datetime']; });
    
    array_multisort(array_column($array, 'datetime'), $array);
    
所有这些技术都是通过引用进行修改的,因此函数没有提供真正有价值的返回值

array\u multisort()

  • 不需要自定义函数
  • 它确实需要通过某种循环机制隔离datetime列
  • 它将丢失数字键,但幸运的是,它们对于这个问题没有价值
usort()

  • 不使用排序方向常量,因此开发人员必须了解
    $a
    之前的
    $b
    (在太空船操作符的任一侧)表示ASC,而
    $b
    之前的
    $a
    表示DESC
  • 需要一个自定义函数
  • 可以通过调用
    uasort()
    来调整以保留第一级键

对于确实需要解析日期或日期时间字符串(因为其格式不允许即时字符串比较)的人,这里是。

在本例中,$array是否需要包含元素$a和$b?-我收到一个错误无效的比较函数nope,
$a
$b
将把数组保存在
$array
中。确保你没有拼错函数名。我不确定我是否理解。在我的示例中,数组中有3个数组-我已经确认了名称,但仍然得到无效的比较函数请参见我添加的解释。我测试了代码,对我来说效果很好!我不知道CodeIgniter,但您是在类中定义函数吗?然后您必须在类之外定义它,或者使用不同的回调参数:
usort($array,array($this,“date\u compare”)
,以便
usort()
知道它是类函数/方法。另见:完全符合我的需要。但是必须将
str\u改为\u upper
改为
strtoupper
。这非常有效。只需将:$originalArray替换为多维数组的名称。并将“datetime”替换为日期子数组字段的名称。谢谢。这个解决方案对我很好。排序选项也很棒(sort\u ASC或sort\u DESC)。非常感谢。只需一个小小的警告就可以很好地工作(要么这样,要么我做错了)。。。我需要排序的日期字段的日期格式为dd/mm/yyyy或yyyy/mm/dd(带斜杠)。在这种情况下,由于某种原因排序不起作用(只按天排序,而不是按整个日期排序)。I-pre-p
usort($array, fn($a, $b) => $a['datetime'] <=> $b['datetime']);
 array_multisort(array_column($array, 'datetime'), SORT_DESC, $array);
array_multisort(array_column($array, 'datetime'), $array);