PHP - usort正在修改数组中对象的内容,如何防止?

时间:2021-11-03 21:32:44

I am using usort with a user comparison function to sort an array of objects. After running usort on an array of these objects, I've found that some of the values of the objects have changed along with their position in the array. What am I missing? I don't believe there are any side effects in my user comparison function. Does usort deconstruct/reconstruct objects some how?

我正在使用usort和用户比较函数对对象数组进行排序。在对这些对象的数组运行usort之后,我发现这些对象的一些值随着它们在数组中的位置发生了变化。我缺少什么?我不相信我的用户比较功能有任何副作用。usort如何解构/重构对象?

Here is the the user comparison function I'm using:

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

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

The objects I'm using look like this :

我使用的对象是这样的:

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"
    }

The property that is changing is the duration property. Before usort is run, every object has a valid float value. After usort, two of them are NaN.

正在更改的属性是duration属性。在运行usort之前,每个对象都有一个有效的浮点值。在usort之后,有两位是NaN。

RESOLUTION:

解决方法:

date_diff has side effects -- at least in my build of PHP. Removing it fixed the issues entirely.

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

2 个解决方案

#1


1  

Off the top of my head, I don't see anything in there that should be modifying the contents of the array elements themselves.

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

The way usort() works is that when it determines the new order of the elements, it adds new elements to the array which holds the value of the originals, then removes the originals, so strictly speaking, none of the elements of the array you passed into the function ever come out, only copies of them do (albeit as part of the same array variable you passed in).

usort()的工作方式是,当它决定元素的新秩序,它将新元素添加到数组拥有原创的价值,然后删除原件,所以严格来说,没有一个数组的元素你传递到函数出来,只有他们做的副本(尽管作为相同的数组变量传入)。

I don't see any reason why usort would destruct and re-construct objects, as you asked, but it does do a similar thing to the array itself. As far as I can tell, nothing in the value of the array elements should be changed, unless you do it explicitly in the comparison function.

我不明白为什么usort会像你说的那样对对象进行破坏和重新构造,但是它对数组本身做了类似的事情。就我所知,数组元素的值中不应该有任何更改,除非您在比较函数中显式地这样做。

In your CompareSegments method, you make calls to a StartDateTime->GetString() method. Is it possible that the GetString() method is modifying your data?

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

#2


0  

What do the objects look like before you apply the usort method, or indeed any method? Without knowing the original state of the objects it is difficult to be conclusive, but NaN is the erroneous result produced by the function passed to usort.

在应用usort方法或者任何方法之前,对象是什么样子的?不知道物体的原始状态是很难确定的,但NaN是传递给usort的函数产生的错误结果。

#1


1  

Off the top of my head, I don't see anything in there that should be modifying the contents of the array elements themselves.

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

The way usort() works is that when it determines the new order of the elements, it adds new elements to the array which holds the value of the originals, then removes the originals, so strictly speaking, none of the elements of the array you passed into the function ever come out, only copies of them do (albeit as part of the same array variable you passed in).

usort()的工作方式是,当它决定元素的新秩序,它将新元素添加到数组拥有原创的价值,然后删除原件,所以严格来说,没有一个数组的元素你传递到函数出来,只有他们做的副本(尽管作为相同的数组变量传入)。

I don't see any reason why usort would destruct and re-construct objects, as you asked, but it does do a similar thing to the array itself. As far as I can tell, nothing in the value of the array elements should be changed, unless you do it explicitly in the comparison function.

我不明白为什么usort会像你说的那样对对象进行破坏和重新构造,但是它对数组本身做了类似的事情。就我所知,数组元素的值中不应该有任何更改,除非您在比较函数中显式地这样做。

In your CompareSegments method, you make calls to a StartDateTime->GetString() method. Is it possible that the GetString() method is modifying your data?

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

#2


0  

What do the objects look like before you apply the usort method, or indeed any method? Without knowing the original state of the objects it is difficult to be conclusive, but NaN is the erroneous result produced by the function passed to usort.

在应用usort方法或者任何方法之前,对象是什么样子的?不知道物体的原始状态是很难确定的,但NaN是传递给usort的函数产生的错误结果。