在php中过滤出多维数组中的值



我有两个数组,使用一个数组(a)来确定需要使用第二个数组(B)中的哪些元素。由于我将多次梳理B,并且每次都不需要以前使用的元素,所以我编写了一个函数,称之为screen_array。

function sift_array(&$array, $key, $value){
   foreach($array as $element){
      if($element[$key] == $value){$temp[] = $element;}
      else{$temp2[] = $element;}
   }
   $array = $temp2;
   return $temp;
}

我很好奇是否有更快的方式来执行此功能。

以下是我如何使用此函数的示例。

在我的网络应用程序中,用户可以设置一个"机器人",在他们离开/注销时执行多次操作。我有一个定期运行的程序来操作机器人。如果机器人是最后一个这样做的机器人,那么它就不能运行相同的操作。

bots数组有3个关键元素:account_id、action_id、job_id作业数组有一个关键元素:job_id。

我传入bots数组,然后对于$key,我传递'job_id',对于$value,我传递正在处理的作业id,比如job1。

$runTheseBots = sift_array($bots, 'job_id', 1);
executeBots($runTheseBots);

这将有更快的执行时间,因为处理作业1的所有机器人都已处理完毕

$runTheseBots = sift_array($bots, 'job_id', 2); 
executeBots($runTheseBots);

有很多方法可以实现这一点,但我只评论一下您是如何做到的:

function sift_array(&$array, $key, $value){
   foreach($array as $i => $element){
      if($element[$key] == $value){
        $temp[] = $element;
        unset($array[$i]);
      }      
   }
   return $temp;
}

在这里,我们通过不复制$array来节省内存和时间(好吧,也许不是时间…基准测试)。将元素移动到新数组后,只需删除即可。

再说一遍,我并不认为这是最好的方法……只是一种优化你已经做过的事情的方法。

我会采用一种折叠方法:

function sift($array, $key, $value) {
    return array_reduce($array, function ($a, $elem) use ($key, $value) {
        $elem[$key] == $value ? $a[0] = $elem : $a[1] = $elem;
    }, array());
}
$bots = sift($array, 'job_id', 2);
executeBots($bots[0]);

此IMO主要通过消除通过引用+返回和返回"分组"数组来改进"接口"。PHP可能能够在内部更好地优化这一点,因此它可以


好吧,一点测试表明它实际上慢了很多

。但是,如果你只过滤你感兴趣的机器人并丢弃其余的,array_filter可以起到推动作用。如果你无论如何都要丢弃,那么完全取消设置不需要的值是迄今为止最快的:

$bots = array();
for ($i = 0; $i < 100000; $i++) {
    $bots = array('job_id' => mt_rand(1, 100));
}
function sift_reduce($array, $key, $value) {
    return array_reduce($array, function ($a, $elem) use ($key, $value) {
        $elem[$key] == $value ? $a[0] = $elem : $a[1] = $elem;
    }, array());
}
function sift_filter($array, $key, $value) {
    return array_filter($array, function ($elem) use ($key, $value) { return $elem[$key] == $value; });
}
function sift_unset(&$array, $key, $value) {
    foreach ($array as $k => $elem) {
        if ($elem[$key] != $value) {
            unset($array[$k]);
        }
    }
}
function sift_array(&$array, $key, $value){
   foreach($array as $element){
      if($element[$key] == $value){$temp[] = $element;}
      else{$temp2[] = $element;}
   }
   $array = $temp2;
   return $temp;
}
$start = microtime(true);
$sifted = sift_reduce($bots, 'job_id', 5);
echo "reduce:  " . (microtime(true) - $start) * 1000 . "n";
$start = microtime(true);
$sifted = sift_filter($bots, 'job_id', 5);
echo "filter:  " . (microtime(true) - $start) * 1000 . "n";
$botsCopy = $bots;
$start = microtime(true);
sift_unset($botsCopy, 'job_id', 5);
echo "unset:   " . (microtime(true) - $start) * 1000 . "n";
$start = microtime(true);
$sifted = sift_array($bots, 'job_id', 5);
echo "array:   " . (microtime(true) - $start) * 1000 . "n";

提供:

reduce:  0.072002410888672
filter:  0.013828277587891
unset:   0.0088214874267578
array:   0.016927719116211

一个更好的选择是称为"Bucket排序"。

如果"桶"的数量相对较少,这是排序最快的选项。

在这种情况下,每个job_id都是一个"bucket"。

你只想筛选一次数组。对于每个元素,根据job_id将其放置在适当的bucket中(每个job_id一个bucket)。

这样,数组只排序一次,并且访问每个作业的所有元素不会消耗任何额外的处理。

如果优化是绝对关键的,你可以有两个或更多的排序函数。排序算法的选择是在运行时根据需要处理的桶和元素的数量进行的。

相关内容

  • 没有找到相关文章

最新更新