【问题标题】:Sorting array of objects by date in object按对象中的日期对对象数组进行排序
【发布时间】:2017-02-01 13:16:38
【问题描述】:

我正在尝试使用源自 Google Calendar Batch 请求的对象对这个数组进行排序,并使用这个带有对象的结果数组:

array(3) {
  ["response-test0"]=>;
  object(Google_Service_Calendar_Events)#46 (17) {
        .
        .
        .
      ["items"]=>;
      array(1) {
        [0]=>;
        array(20) {
            .
            .
          ["start"]=>;
          array(1) {
            ["dateTime"]=>;
            string(25) "2017-02-01T10:00:00+01:00"
          } 
        .
        .
        .
  ["response-test1"]=>;
  object(Google_Service_Calendar_Events)#46 (17) {
        .
        .
        .
      ["items"]=>;
      array(1) {
        [0]=>;
        array(20) {
            .
            .
          ["start"]=>;
          array(1) {
            ["dateTime"]=>;
            string(25) "2017-02-01T11:00:00+01:00"
          }
        .
        .
        .
  ["response-test3"]=>;
  object(Google_Service_Calendar_Events)#46 (17) {
        .
        .
        .
      ["items"]=>;
      array(1) {
        [0]=>;
        array(20) {
            .
            .
          ["start"]=>;
          array(1) {
            ["dateTime"]=>;
            string(25) "2017-02-01T11:00:00+01:00"
          }
        .
        .

这是获取数据的代码:

$arrlength = count($calendarId);
for ($x = 0; $x <= $arrlength-1; $x++) {
    $results = $service->events->listEvents($calendarId[$x], $optParams);
    $batch->add($results, "test" .$x);
};
$results = $batch->execute();

结果数组包含您(在本例中)名为 ["response-test0"]、["response-test1"] 和 ["response-test2"] 的对象,如我的数组所示例子。

编辑:据我所知,答案中似乎缺少数组对象与关联数组复杂的事实(或者我错了)?对象内部搜索的建议似乎在正确的方向,但我无法完全测试这一点,因为没有考虑“顶级”['response_x']。

开始日期排序的结构(不是在每个对象中单独排序日期):

array(3) {
    ["response-test0"]
    Object(Google_Service_Calendar_Events)#46(17){
    .
    .
    }
    ["response-test1"]
    Object(Google_Service_Calendar_Events)#46(17){
    .
    .
    }
    ["response-test2"]
    Object(Google_Service_Calendar_Events)#46(17){
    .
    .
    }

我已经尝试使用这个 sn-p(和许多其他)按日期([“start”])对单个项目进行排序 - 日历会议的开始,但到目前为止没有运气。我也研究过合并对象,但没有运气。我是 PHP 的新手,但对编程的基础知识相当了解,所以我希望有人能指出我正确的方向 - 我会很感激:

usort($results, function($a, $b) {
    return $a['items']['start'] - $b['items']['start'];
});

var_dump( $results );

【问题讨论】:

  • 请尝试使用strtotime($a['items']['start']) - strtotime($b['items']['start']) 或更好地创建DateTime object,然后在usort 中子您的值
  • 因为我不需要 ["response-testx"] 级别 - 有没有办法合并或展平数组 - 将所有记录向上移动一步,并摆脱 ['response -testx'] 级别?
  • @petrusjak 如果你想减小数组大小,我更新了答案。

标签: php arrays sorting google-calendar-api google-api-php-client


【解决方案1】:

您可以使用 DateTime 对象来比较日期:

function cmpDate($a, $b) {
    // To confirm expected result, dump the data for inspection.
    //var_dump($a);
    //var_dump($b);

    // Option 1:
    //$date1 = new \DateTime($a['items'][0]['start']['dateTime'])->getTimestamp();
    //$date2 = new \DateTime($b['items'][0]['start']['dateTime'])->getTimestamp();

    // Option 2
    $date1 = new \DateTime($a->items[0]['start']['dateTime'])->getTimestamp();
    $date2 = new \DateTime($b->items[0]['start']['dateTime'])->getTimestamp();

    // usort compares integers and orders it accordingly.
    return $date1 - $date2;
}

usort($results, 'cmpDate');

我正在使用时间戳,因此您不需要将日期格式化为字符串。

来源:

http://php.net/manual/en/class.datetime.php

http://php.net/manual/en/function.usort.php

针对您关于通过删除第一层来重新排列数组的评论,您可以尝试以下操作。请注意,要知道哪个记录是哪个记录,这些键可能很重要。

$newArr = [];
foreach ($results as $key => $data) {
    // echo $key; // response-test0
    // You can reduce the array as much as you like.
    // $newArr[] = $data;
    // $newArr[] = $data->items['start'];
    $newArr[] = $data->items['start']['dateTime'];

    // In case you want to preserve the key
    // $newArr[$key] = $data->items['start']['dateTime'];

}

【讨论】:

  • 你能帮我找到正确的“路径”到 ['start'] 吗?如果 $a["items"]['start'] 是正确的,不 shure - 我想我错过了一些东西。
  • @petrusjak 我已经更新了代码。你很亲密。 $a 是一个对象,应该被引用为 ->.
  • 抱歉 - 我收到语法错误:$date1 = new \DateTime($a->items[0]['start']['dateTime'])->getTimeStamp(); $date2 = new \DateTime($b->items[0]['start']['dateTime'])->getTimeStamp();
  • PHP 解析错误:语法错误,第 62 行 C:\inetpub\gadgetsite\infotavle.php 中的意外 '->' (T_OBJECT_OPERATOR)
  • 你能把 $a 和 $b 的输出贴在 cmpDate 中吗?请参阅更新的答案。我删除了 abs()。不需要。
【解决方案2】:

我自己找到了一个可行的解决方案,通过构造一个更易于管理的数组进行排序(接近 Nitin 的建议),循环遍历来自日历 API 的结果数组。对于其他可能有同样问题的人,我在这里发布相关部分。我确信我的代码可以优化并在语义上看起来更好,但它确实有效:

function cmpDate($a, $b) {
    $date1 = new DateTime($a['start']);
    $date2 = new DateTime($b['start']);

    $date1 = $date1->getTimestamp();
    $date2 = $date2->getTimestamp();
    return $date1 - $date2;
}

$y = 0;
for ($x = 0; $x <= $arrlength-1; $x++) {
if (count($results["response-test".$x.""]->getItems()) == 0) {

} else {

  foreach ($results["response-test".$x.""]->getItems() as $event) {
    $start = $event->start->dateTime;
    $dato = date_format(date_create($start), "d.m.Y");
    $s = strtotime($start);
    if (empty($start)) {
      $start = $event->start->date;
    }
    $tid = new dateTime($start);
    $data[$y]['start'] = $start;
    $data[$y]['dato'] = $dato;
    $data[$y]['tid'] = $tid->format('H:i');
    $data[$y]['lokasjon'] = $event->getLocation();
    $data[$y]['organisator'] = $event->getOrganizer()->email;
    $data[$y]['tema'] = $event->getSummary();
    $y++;
  }
}
usort($data, 'cmpDate');

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-30
    • 2015-02-25
    • 2013-10-26
    • 1970-01-01
    相关资源
    最近更新 更多