数组过滤器和数组值在大型PHP对象数组上花费很长时间
我有一段运行模拟的代码数组过滤器和数组值在大型PHP对象数组上花费很长时间,php,arrays,Php,Arrays,我有一段运行模拟的代码 public function cleanUpHouses(\DeadStreet\ValueObject\House\Collection $collection) { $houses = $collection->getHouses(); $housesLength = count($houses); $filterValues = false; for($i = 0; $i < $housesLength; $i++)
public function cleanUpHouses(\DeadStreet\ValueObject\House\Collection $collection)
{
$houses = $collection->getHouses();
$housesLength = count($houses);
$filterValues = false;
for($i = 0; $i < $housesLength; $i++) {
if(!$this->houseModel->hasBeenAttacked($houses[$i])) {
break;
}
$houses[$i]->setCurrentAttackers(0);
if($this->houseModel->requiresDestroying($houses[$i])) {
$houses[$i] = null;
$filterValues = true;
}
}
if($filterValues) {
$houses = array_values(array_filter($houses));
}
$collection->setHouses($houses);
return $collection;
}
公共功能清理室(\DeadStreet\ValueObject\House\Collection$Collection)
{
$houses=$collection->getHouses();
$housesLength=计数($houses);
$filterValues=false;
对于($i=0;$i<$housesLength;$i++){
如果(!$this->houseModel->hasbeenatacked($houses[$i])){
打破
}
$houses[$i]>setCurrent攻击者(0);
如果($this->houseModel->requiresDistroming($houses[$i])){
$houses[$i]=null;
$filterValues=true;
}
}
如果($filterValues){
$houses=数组_值(数组_过滤器($houses));
}
$collection->sethouse($houses);
退回$collection;
}
但是,$collection
包含一个数组($getHouses
),该数组最多包含100万个结果,尽管它永远不需要迭代所有这些结果,但行$houses=array\u值(array\u filter($houses))
由于数组的大小(每次运行该行最多3秒)而需要较长时间
我必须保持数组索引为数值,并且这个数组中不能有空值
我希望unset($array[$I])
会在元素在键中“down”后移动数组元素,因此如果我要unset($array[5])
,那么$array[6]
将变成$array[5]
,但它似乎不是这样工作的
中断
条件存在,因为在迭代中,如果迭代中的房屋没有受到攻击,那么可以安全地假设阵列中的任何其他房屋也没有受到攻击
是否有一种优化的、资源较少的方法来实现这一点
目前我还不能真正地重新构造它,因为它是在单元测试中,我需要尽快完成它,这种方法不是很好,但是呃。我认为实现这一点最简单的方法是这样的: 当您在房屋数组中循环时,需要取消设置数组中的某些内容,您可以欺骗循环本身
if($this->houseModel->requiresDestroying($houses[$i])) {
// $houses[$i] = null;
// when you unset the $i house in the array,
// you can simply switch it with the last one in the array, keeping in mind,
// that this may break your logic with the break condition, so will want to change that as well.
$lastHouse = $houses[$housesLength - 1];
$houses[$i] = $lastHouse;
unset($houses[$housesLength - 1]);
$i--;
$housesLength--; // by doing the top two lines we would make the loop check the last house again.
$shouldBreak = false; // this will keep your logic with the break if later.
// $filterValues = true; // you can remove this line here.
}
您可能希望在for循环开始之前为break条件设置一个变量
$shouldBreak = true;
for($i = 0; $i < $housesLength; $i++) {
...
我们只删除数组中的最后一个元素,因此它将保持为数字。我认为实现这一点最简单的方法是: 当您在房屋数组中循环时,需要取消设置数组中的某些内容,您可以欺骗循环本身
if($this->houseModel->requiresDestroying($houses[$i])) {
// $houses[$i] = null;
// when you unset the $i house in the array,
// you can simply switch it with the last one in the array, keeping in mind,
// that this may break your logic with the break condition, so will want to change that as well.
$lastHouse = $houses[$housesLength - 1];
$houses[$i] = $lastHouse;
unset($houses[$housesLength - 1]);
$i--;
$housesLength--; // by doing the top two lines we would make the loop check the last house again.
$shouldBreak = false; // this will keep your logic with the break if later.
// $filterValues = true; // you can remove this line here.
}
您可能希望在for循环开始之前为break条件设置一个变量
$shouldBreak = true;
for($i = 0; $i < $housesLength; $i++) {
...
我们只删除数组中的最后一个元素,因此它将保持为数字