我有两个数组,使用一个数组(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)。
这样,数组只排序一次,并且访问每个作业的所有元素不会消耗任何额外的处理。
如果优化是绝对关键的,你可以有两个或更多的排序函数。排序算法的选择是在运行时根据需要处理的桶和元素的数量进行的。