PHP数组交集的优化代码分析

 更新时间:2011年03月06日 21:55:10   作者:  
假设我们正在运营一个手机相关的网站,用户可以通过指定若干参数(如操作系统,屏幕分辨率,摄像头像素等等)来筛选自己想要的手机。
不过由于手机的参数多,且不同的手机其参数差异大,所以参数表结构通常是纵表(一个参数是一行),而不是横表(一个参数是一列),此时使用若干参数来取结果,通常就是把每个单独参数来取结果,再一起取交集。
假定每个参数会包含一千个左右的唯一结果(id int),以此为前提来模拟生成一些数据:
复制代码 代码如下:

<?php
$rand = function() {
$result = array();
for ($i = 0; $i < 1000; null) {
$value = mt_rand(1, 10000);
if (!isset($result[$value])) {
$result[$value] = null;
$i++;
}
}
return array_keys($result);
};
$param_a = $rand();
$param_b = $rand();
?>

注意:如果测试数据集过小的话,结论可能会出现不一致,先来看看通过PHP内置方法array_intersect实现的性能:
复制代码 代码如下:

<?php
$time = microtime(true);
$result = array_intersect($param_a, $param_b);
$time = microtime(true) - $time;
echo "array_intersect: {$time}\n";
?>

再来看看通过自定义方法intersect实现的性能:
复制代码 代码如下:

<?php
function intersect() {
if (func_num_args() < 2) {
trigger_error('param error', E_USER_ERROR);
}
$args = func_get_args();
foreach ($args AS $arg) {
if (!is_array($arg)) {
trigger_error('param error', E_USER_ERROR);
}
}
$intersect = function($a, $b) {
$result = array();
$length_a = count($a);
$length_b = count($b);
for ($i = 0, $j = 0; $i < $length_a && $j < $length_b; null) {
if($a[$i] < $b[$j]) {
$i++;
} else if($a[$i] > $b[$j]) {
$j++;
} else {
$result[] = $a[$i];
$i++;
$j++;
}
}
return $result;
};
$result = array_shift($args);
sort($result);
foreach ($args as $arg) {
sort($arg);
$result = $intersect($result, $arg);
}
return $result;
}
$time = microtime(true);
$result = intersect($param_a, $param_b);
$time = microtime(true) - $time;
echo "intersect: {$time}\n";
?>

直觉上,我们肯定会认为内置函数快于自定义函数,但本例中结果恰恰相反:
array_intersect: 0.023918151855469
intersect: 0.0026049613952637
需要提醒大家的是,array_intersect和intersect在功能上并不完全等价,例子如下:
复制代码 代码如下:

$param_a = array(1, 2, 2);
$param_b = array(1, 2, 3);
var_dump(
array_intersect($param_a, $param_b),
intersect($param_a, $param_b)
);

array_intersect: 1, 2, 2
intersect: 1, 2
也就是说,如果在第一个数组参数中有重复元素的话,则array_intersect会返回所有满足条件的重复元素,而不是仅仅返回一个,有兴趣的读者可以变换一下参数顺序再看结果。
再唠叨一下,最初我写intersect方法时,大概写成下面这个样子:
复制代码 代码如下:

<?php
function intersect() {
if (func_num_args() < 2) {
trigger_error('param error', E_USER_ERROR);
}
$args = func_get_args();
foreach ($args AS $arg) {
if (!is_array($arg)) {
trigger_error('param error', E_USER_ERROR);
}
}
$result = array();
$data = array_count_values(
call_user_func_array('array_merge', $args)
);
foreach ($data AS $value => $count) {
if ($count > 1) {
$result[] = $value;
}
}
return $result;
}
?>

代码更简洁,不过有一个弊端,因为使用了array_merge,所以当数组中元素非常多的时候,占用的内存会比较大,反之如果数组中元素不是非常多,那么此方法也是可行的。(来源:火丁笔记)

相关文章

  • php缓冲 output_buffering的使用详解

    php缓冲 output_buffering的使用详解

    本篇文章是对php缓冲output_buffering进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • PHP判断函数是否被定义的方法

    PHP判断函数是否被定义的方法

    在本篇文章里小编给大家分享了关于PHP判断函数是否被定义的相关方法和知识点,需要的朋友们参考下。
    2019-06-06
  • php字符串函数 str类常见用法示例

    php字符串函数 str类常见用法示例

    这篇文章主要介绍了php字符串函数 str类常见用法,结合实例形式分析了php字符串函数常见操作技巧与相关注意事项,需要的朋友可以参考下
    2020-05-05
  • php IP及IP段进行访问限制的代码

    php IP及IP段进行访问限制的代码

    本来是写了几个函数,IP黑名单是记到库里的,为了方便理解,改成了一个class把IP黑名单写了出来。
    2008-12-12
  • PHP实现将base64编码字符串转换成图片示例

    PHP实现将base64编码字符串转换成图片示例

    这篇文章主要介绍了PHP实现将base64编码字符串转换成图片,涉及php编码转换、文件读写等简单处理技巧,需要的朋友可以参考下
    2018-06-06
  • php实现基于pdo的事务处理方法示例

    php实现基于pdo的事务处理方法示例

    这篇文章主要介绍了php实现基于pdo的事务处理方法,结合实例形式分析了php使用pdo进行事务操作的相关实现技巧,需要的朋友可以参考下
    2017-07-07
  • Php部分常见问题总结

    Php部分常见问题总结

    [红色]Php部分常见问题总结...
    2006-12-12
  • PHP预定义超全局数组变量小结

    PHP预定义超全局数组变量小结

    这篇文章主要介绍了PHP预定义超全局数组变量,结合实例形式总结分析了预定义超全局数组变量的特性、功能、使用方法及相关操作注意事项,需要的朋友可以参考下
    2018-08-08
  • WordPress网站性能优化指南

    WordPress网站性能优化指南

    很多博主都会感觉WordPress很慢?作为全世界最常用的建站和博客系统WordPress来说,在性能设计上肯定不会有太大的问题,WordPress开发团队也肯定也考虑到这个问题。那么 WordPress 效率问题主要是出在哪里呢?今天就给大家讲讲自己多年总结的 WordPress优化经验和技巧
    2015-11-11
  • 字符串长度函数strlen和mb_strlen的区别示例介绍

    字符串长度函数strlen和mb_strlen的区别示例介绍

    strlen和mb_strlen的区别,但是对于一些初学者来说,如果不看手册,也许不太清楚其中的区别,下面与大家分享下两者之间的区别
    2014-09-09

最新评论