简体   繁体   English

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

[英]PHP Sort a multidimensional array by element containing date

I have an array such as:我有一个数组,例如:

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
    )

)

Can anyone suggest a way to sort/order this based on the datetime element?任何人都可以建议一种基于日期时间元素对其进行排序/排序的方法吗?

Use usort() and a custom comparison function:使用usort()和自定义比较函数:

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

EDIT : Your data is organized in an array of arrays.编辑:您的数据组织在数组数组中。 To better distinguish those, let's call the inner arrays (data) records, so that your data really is an array of records.为了更好地区分这些,我们将内部数组(数据)称为记录,这样您的数据实际上就是一个记录数组。

usort will pass two of these records to the given comparison function date_compare() at aa time. usort将一次将这些记录中的两条传递给给定的比较函数date_compare() date_compare then extracts the "datetime" field of each record as a UNIX timestamp (an integer), and returns the difference, so that the result will be 0 if both dates are equal, a positive number if the first one ( $a ) is larger or a negative value if the second argument ( $b ) is larger. date_compare然后将每条记录的"datetime"字段提取为 UNIX 时间戳(整数),并返回差值,因此如果两个日期相等,则结果将为0 ,如果第一个 ( $a ) 是正数如果第二个参数 ( $b ) 更大,则更大或负值。 usort() uses this information to sort the array. usort()使用此信息对数组进行排序。

This should work.这应该有效。 I converted the date to unix time via strtotime.我通过 strtotime 将日期转换为 unix 时间。

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

One-liner version would be using multiple array methods:单行版本将使用多种数组方法:

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

From php7 you can use the Spaceship operator :在 php7 中,您可以使用Spaceship 运算符

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

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

http://us2.php.net/manual/en/function.array-multisort.php see third example: http://us2.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);

?>

fyi, using a unix (seconds from 1970) or mysql timestamp (YmdHis - 20100526014500) would be be easier for the parser but i think in your case it makes no difference.仅供参考,使用unix(从1970年开始的秒数)或mysql时间戳(YmdHis - 20100526014500)对解析器来说会更容易,但我认为在你的情况下它没有区别。

You can simply solve this problem using usort() with callback function.您可以使用带有回调函数的usort()简单地解决这个问题。 No need to write any custom function.无需编写任何自定义函数。

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

Sorting array of records/assoc_arrays by specified mysql datetime field and by order:按指定的 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));

I came across to this post but I wanted to sort by time when returning the items inside my class and I got an error.我遇到了这篇文章,但我想在返回班级中的项目时按时间排序,但出现错误。

So I research the php.net website and end up doing this:所以我研究了 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"];
   }
}

You can find very useful examples in the PHP.net website您可以在PHP.net 网站中找到非常有用的示例

My array looked like this:我的阵列看起来像这样:

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

For those still looking a solved it this way inside a class with a function sortByDate, see the code below对于那些仍在使用 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;

    }
}

For 'd/m/Y' dates:对于'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;
});

where $i is the array index其中$i是数组索引

Most of the earlier answers failed to acknowledge the available shortcut of comparing the datetime values as simple strings.大多数较早的答案未能承认将日期时间值作为简单字符串进行比较的可用快捷方式。 Other answers that realized that strtotime() was unnecessary did not spell out why did what they did ...so I will.其他意识到strtotime()是不必要的答案并没有说明为什么strtotime() ……所以我会的。

Because your datetime values are formatted with units in descending size ( Y , m , d , H , i , s ) AND because each unit is consistently expressed with the same number of characters (4, 2, 2, 2, 2, 2) AND because the delimiting characters are all identical from string to string, you can simply compare them character-by-character from left to right (naturally).因为您的datetime值的格式是按降序大小的单位 ( Y , m , d , H , i , s ) 并且因为每个单位始终用相同数量的字符 (4, 2, 2, 2, 2, 2) 表示并且因为分隔符从字符串到字符串都是相同的,您可以简单地从左到右逐个字符地比较它们(自然)。 This would not be true for a date string formatted as, say, d/m/Y .对于格式为d/m/Y的日期字符串,情况并非如此。

There are two functions that are ideal for this task, I'll demonstrate ASC and DESC versions for both.有两个函数非常适合此任务,我将演示两者的 ASC 和 DESC 版本。

Demo Link演示链接

  • usort() by date column DESC: usort() 按日期列 DESC:

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

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

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

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

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

All of these techniques modify by reference, so the function provide no real valuable return value.所有这些技术都是通过引用修改的,因此该函数没有提供真正有价值的返回值。

array_multisort() : array_multisort()

  • doesn't need a custom function不需要自定义函数
  • it does need the datetime column to be isolated by some looping mechanism它确实需要通过某种循环机制隔离日期时间列
  • it will lose numeric keys, but fortunately they are not valuable for this question它会丢失数字键,但幸运的是它们对这个问题没有价值

usort() : usort()

  • doesn't use sorting direction constants, so developers must understand that $a before $b (on either side of the spaceship operator) means ASC and $b before $a means DESC不使用排序方向的常数,所以开发人员必须明白, $a$b (在飞船操作者的任一侧)指ASC和$b之前$a装置DESC
  • requires a custom function需要自定义函数
  • can be adjusted to preserve first level keys by calling uasort() instead可以通过调用uasort()来调整以保留第一级键

For anyone who truly DOES need a date or datetime string to be parsed because its format does not permit instant string comparisons, here is an answer devoted to explaining the caveats of that task .对于真正需要解析日期或日期时间字符串的任何人,因为其格式不允许即时字符串比较,这里有一个专门解释该任务注意事项的答案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM