PHP--usort正在修改数组中对象的内容,如何防止这种情况发生?
我使用usort和用户比较函数对对象数组进行排序。在对这些对象的数组运行usort之后,我发现这些对象的一些值随着它们在数组中的位置而改变。我错过了什么?我不相信我的用户比较功能有任何副作用。usort如何解构/重建对象 下面是我正在使用的用户比较函数:PHP--usort正在修改数组中对象的内容,如何防止这种情况发生?,php,sorting,usort,Php,Sorting,Usort,我使用usort和用户比较函数对对象数组进行排序。在对这些对象的数组运行usort之后,我发现这些对象的一些值随着它们在数组中的位置而改变。我错过了什么?我不相信我的用户比较功能有任何副作用。usort如何解构/重建对象 下面是我正在使用的用户比较函数: private function SortArrayOfSegments($segments){ foreach($segments as $segment){ echo '<pre>'; v
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;
}
}
正在更改的属性是duration属性。在运行usort之前,每个对象都有一个有效的浮点值。在usort之后,其中两个是NaN
分辨率:
date_diff有副作用——至少在我构建的PHP中是这样。删除它完全解决了问题
公共静态函数比较段($a,$b){
$adate=新日期时间($a->StartDateTime->GetString());
$bdate=newdatetime($b->StartDateTime->GetString());
$lessThan=$adate<$bdate;
$equal=$adate==$bdate;
$greaterThan=$adate>$bdate;
如果($lessThan){
返回-1;
}否则,如果($equal){
返回0;
}否则{
返回1;
}
}
在我的脑海中,我没有看到任何应该修改数组元素本身内容的内容
其工作方式是,当它确定元素的新顺序时,它会将新元素添加到保存原始元素值的数组中,然后删除原始元素,因此严格地说,传递到函数中的数组中的所有元素都不会出现,只有它们的副本才会出现(尽管是作为传入的同一数组变量的一部分)
我不明白为什么usort
会像您要求的那样解构和重新构造对象,但它确实对数组本身做了类似的事情。据我所知,数组元素的值不应该更改,除非您在比较函数中显式执行
在
CompareSegments
方法中,调用StartDateTime->GetString()
方法。是否可能是GetString()方法
方法正在修改您的数据?在应用usort方法或任何方法之前,对象是什么样子的?如果不知道对象的原始状态,很难得出结论,但NaN是传递给usort的函数产生的错误结果。我假设如果使用旧的ob,它仍然会损坏对象回调语法:usort($segments,array('AirObject','CompareSegments'))
?它现在可以工作了,我把它改成了那个语法…但这很奇怪。如果我在SortarayOfSegments函数中var_dump,它会显示出损坏,如果我在该函数调用之外var_dump,一切都是格式良好的…奇怪。你使用的是哪个PHP版本?5.3.0,这个版本还是以前的版本有已知的bug?虽然看起来很奇怪它现在正在工作我无法解释为什么属性在函数中损坏,但当它返回时却无法解释。如果您在比较程序中转储正在排序的整个对象,那么您可能会看到“损坏”实际上处于未定义状态。不幸的是,它没有副作用。请尝试在usort外部直接调用CompareSegments
,通过引用传入两个数组元素(就像在usort中一样),并检查它们是否以这种方式损坏。显然,请确保在usort中使用至少一个损坏的元素。不,没有副作用或损坏。
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"
}
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;
}
}