PHP -- usort 正在修改数组中对象的内容,我该如何防止这种情况发生?

标签 php sorting usort

我正在使用带有用户比较功能的 usort 对对象数组进行排序。在对这些对象的数组运行 usort 之后,我发现对象的一些值随着它们在数组中的位置而改变。我错过了什么?我不相信我的用户比较功能有任何副作用。 usort 是否以某种方式解构/重建对象?

这是我正在使用的用户比较功能:

private function SortArrayOfSegments($segments){
    foreach($segments as $segment){
        echo '<pre>';
        var_dump($segment);  
    }
    usort($segments, "AirObject::CompareSegments");
    foreach($segments as $segment){
        var_dump($segment);
        echo '</pre>';
     }
    return $segments;
}

public static function CompareSegments($a, $b){
    $interval = date_diff(date_create($a->StartDateTime->GetString()),
                date_create($b->StartDateTime->GetString()));
    if($interval->invert == 1){
        return 1;   
    }else if($interval->y == 0 && $interval->m == 0  && $interval->d == 0 
    && $interval->i == 0 && $interval->s == 0 && $interval->h == 0){
        return 0;   
    }else if($interval->invert == 0){
        return -1;  
    }  
}

我正在使用的对象如下所示:

object(AirSegment)#14 (12) {
      ["StartDateTime"]=>
      object(VDateTime)#27 (4) {
        ["date"]=>
        string(10) "2010-12-07"
        ["time"]=>
        string(8) "09:23:21"
        ["timezone"]=>
        string(0) ""
        ["utc_offset"]=>
        string(0) ""
      }
      ["EndDateTime"]=>
      object(VDateTime)#23 (4) {
        ["date"]=>
        string(10) "2010-12-07"
        ["time"]=>
        string(8) "13:23:21"
        ["timezone"]=>
        string(0) ""
        ["utc_offset"]=>
        string(0) ""
      }
      ["start_airport_code"]=>
      string(3) "SFO"
      ["start_city_name"]=>
      string(13) "San Francisco"
      ["end_airport_code"]=>
      string(3) "STL"
      ["end_city_name"]=>
      string(8) "St Louis"
      ["operating_airline"]=>
      string(15) "United Airlines"
      ["operating_flight_number"]=>
      string(3) "335"
      ["duration"]=>
      float(NAN)
      ["required_properties":protected]=>
      array(9) {
        ["StartDateTime"]=>
        bool(false)
        ["EndDateTime"]=>
        bool(false)
        ["start_airport_code"]=>
        bool(false)
        ["end_airport_code"]=>
        bool(false)
        ["operating_airline"]=>
        bool(false)
        ["operating_flight_number"]=>
        bool(false)
        ["start_city_name"]=>
        bool(false)
        ["end_city_name"]=>
        bool(false)
        ["service_class"]=>
        bool(true)
      }
      ["service_class"]=>
      string(5) "Coach"
      ["trip_id"]=>
      string(4) "1621"
    }

正在更改的属性是持续时间属性。在运行 usort 之前,每个对象都有一个有效的浮点值。经过usort,其中两个是NaN。

解决方案:

date_diff 有副作用——至少在我构建的 PHP 中是这样。删除它可以完全解决问题。

public static function CompareSegments($a, $b){
    $adate = new DateTime($a->StartDateTime->GetString());
    $bdate = new DateTime($b->StartDateTime->GetString());
    $lessThan = $adate < $bdate;
    $equal = $adate == $bdate;
    $greaterThan = $adate > $bdate;

    if($lessThan){
        return -1;  
    }else if($equal){
        return 0;   
    }else{
        return 1;   
    }
}

最佳答案

在我的脑海中,我没有看到任何应该修改数组元素本身内容的内容。

方式usort()有效的是,当它确定元素的新顺序时,它会将新元素添加到保存原件值的数组中,然后删除原件,所以严格来说,你传递给函数的数组元素都没有出来,只有它们的副本可以(尽管作为您传入的同一数组变量的一部分)。

我不明白为什么 usort 会像您所问的那样销毁和重建对象,但它确实对数组本身做了类似的事情。据我所知,数组元素的值不应更改,除非您在比较函数中明确地这样做。

在您的 CompareSegments 方法中,您调用了 StartDateTime->GetString() 方法。 GetString() 方法是否可能正在修改您的数据?

关于PHP -- usort 正在修改数组中对象的内容,我该如何防止这种情况发生?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4419902/

相关文章:

php - PHP 操作码与实际执行的二进制代码有何关系?

java - 按从最高-> 最低的每个字符串解析的整数对 ArrayList<String> 进行排序?

php - 如何按嵌套在其中的元素对 PHP 数组进行排序?

PHP uSort 优化?

php - 创建存储库方法,将信息记录到数据库(mysql)表中。

php - 单击按钮时使用 ID 进行 SQL 查询

sql - 我需要在 SQL Server 2008 数据库中使用这么多索引吗?

php - 如何按日期字段降序对数组进行排序?

php - Zend_Pdf 添加文本链接到 pdf 页面

arrays - 按总位数对数字数组进行排序