PHP 按包含 Y-m-d H:i:s 日期的元素对多维数组进行排序

问题描述 投票:0回答:11

我有一个数组,例如:

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
    )

)

任何人都可以建议一种根据日期时间元素进行排序/排序的方法吗?

php datetime arrays sorting
11个回答
240
投票

使用

usort()
和自定义比较函数:

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

您的数据被组织在数组的数组中。为了更好地区分这些,我们将内部数组(数据)称为记录,这样您的数据实际上是一个记录数组。

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


61
投票

这应该有效。我通过 strtotime 将日期转换为 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);

49
投票

从 php7 开始,您可以使用 Spaceship 运算符

usort($array, function($a, $b) {
  return new DateTime($a['datetime']) <=> new DateTime($b['datetime']);
});

8
投票

https://www.php.net/manual/en/function.array-multisort.php 请参阅第三个示例:

<?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)对于解析器来说会更容易,但我认为在你的情况下没有什么区别。


7
投票

大多数早期答案都没有承认将日期时间值作为简单字符串进行比较的可用快捷方式。 其他意识到

strtotime()
是不必要的答案并没有说明为什么他们这样做......所以我会的。

因为您的

datetime
值采用降序排列的单位格式(
Y
m
d
H
i
s
)并且因为每个单位都一致地用相同的数字表示字符 (4, 2, 2, 2, 2, 2) AND 因为字符串之间的分隔字符都是相同的,所以您可以简单地从左到右逐个字符地比较它们(自然地)。 对于格式为
d/m/Y
的日期字符串来说,情况并非如此。

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

演示链接

  • usort() 按日期列 DESC:

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

    usort($array, function($a, $b) { return $a['datetime'] <=> $b['datetime']; });
    
  • usort() 按日期列 ASC (>= PHP7.4):

    usort($array, fn($a, $b) => $a['datetime'] <=> $b['datetime']);
    
  • array_multisort() 按日期列 DESC:

     array_multisort(array_column($array, 'datetime'), SORT_DESC, $array);
    
  • array_multisort() 按日期列 ASC:

    array_multisort(array_column($array, 'datetime'), $array);
    

所有这些技术都是通过引用进行修改,因此该函数没有提供真正有价值的返回值。

array_multisort()

  • 不需要自定义功能
  • 它确实需要通过某种循环机制来隔离日期时间列
  • 它会丢失数字键,但幸运的是它们对于这个问题没有价值

usort()

  • 不使用排序方向常量,因此开发人员必须了解
    $a
    之前的
    $b
    (在宇宙飞船运算符的任一侧)表示 ASC,
    $b
    之前的
    $a
    表示 DESC
  • 需要自定义功能
  • 可以通过调用
    uasort()
    来调整以保留第一级密钥

对于真正需要解析日期或日期时间字符串的人,因为其格式不允许即时字符串比较,这里是专门用于解释该任务的注意事项的答案


6
投票

$array = 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
   )

   );
   print_r($array);   
   $name = 'datetime';
   usort($array, function ($a, $b) use(&$name){
      return $a[$name] - $b[$name];});

   print_r($array);

6
投票

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

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

5
投票

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

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));

2
投票

我看到了这篇文章,但我想在返回班级内的项目时按时间排序,但出现错误。

所以我研究了 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"];
   }
}

您可以在 PHP.net 网站

找到非常有用的示例

我的数组看起来像这样:

  '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)

2
投票

对于那些仍然希望在具有函数 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;

    }
}

1
投票

对于

'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
是数组索引

© www.soinside.com 2019 - 2024. All rights reserved.