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


Posted in PHP onMarch 06, 2011

不过由于手机的参数多,且不同的手机其参数差异大,所以参数表结构通常是纵表(一个参数是一行),而不是横表(一个参数是一列),此时使用若干参数来取结果,通常就是把每个单独参数来取结果,再一起取交集。
假定每个参数会包含一千个左右的唯一结果(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 相关文章推荐
phpMyAdmin2.11.6安装配置方法
Aug 24 PHP
php visitFile()遍历指定文件夹函数
Aug 21 PHP
php empty,isset,is_null判断比较(差异与异同)
Oct 19 PHP
php中修改浏览器的User-Agent来伪装你的浏览器和操作系统
Jul 29 PHP
php-fpm配置详解
Feb 12 PHP
PHP SplObjectStorage使用实例
May 12 PHP
PHP多文件上传实例
Jul 09 PHP
php上传图片获取路径及给表单字段赋值的方法
Jan 23 PHP
PHP7 新特性详细介绍
Sep 06 PHP
PHP数组生成XML格式数据的封装类实例
Nov 10 PHP
ThinkPHP实现图片上传操作的方法详解
May 08 PHP
Windows上php5.6操作mongodb数据库示例【配置、连接、获取实例】
Feb 13 PHP
php下安装配置fckeditor编辑器的方法
Mar 02 #PHP
PHP如何抛出异常处理错误
Mar 02 #PHP
php中实现记住密码自动登录的代码
Mar 02 #PHP
防止用户利用PHP代码DOS造成用光网络带宽
Mar 01 #PHP
php Smarty 字符比较代码
Feb 27 #PHP
php下批量挂马和批量清马代码
Feb 27 #PHP
php SQL Injection with MySQL
Feb 27 #PHP
You might like
域名查询代码公布
2006/10/09 PHP
一个简单的PHP入门源程序
2006/10/09 PHP
介绍php设计模式中的工厂模式
2008/06/12 PHP
删除无限分类并同时删除它下面的所有子分类的方法
2010/08/08 PHP
PHP正确配置mysql(apache环境)
2011/08/28 PHP
PHP实现将上传图片自动缩放到指定分辨率,并保持清晰度封装类示例
2019/06/17 PHP
Google Suggest ;-) 基于js的动态下拉菜单
2006/10/11 Javascript
自己的js工具 Cookie 封装
2009/08/21 Javascript
CSS+jQuery实现的一个放大缩小动画效果
2013/09/24 Javascript
使用POST方式弹出窗口的两种方法示例介绍
2014/01/29 Javascript
JS模拟键盘打字效果的方法
2015/08/05 Javascript
Node.js的MongoDB驱动Mongoose基本使用教程
2016/03/01 Javascript
jquery实现一个简单的表单验证实例
2016/03/30 Javascript
详解angularjs中如何实现控制器和指令之间交互
2017/05/31 Javascript
vue使用 better-scroll的参数和方法详解
2018/01/25 Javascript
layui form.render('select', 'test2') 更新渲染的方法
2019/09/27 Javascript
JS使用正则表达式提交页面验证的代码
2019/10/16 Javascript
[02:12]2019完美世界全国高校联赛(春季赛)报名开启
2019/03/01 DOTA
windows下python模拟鼠标点击和键盘输示例
2014/02/28 Python
利用Python获取操作系统信息实例
2016/09/02 Python
详解Python中最难理解的点-装饰器
2017/04/03 Python
Python实现修改文件内容的方法分析
2018/03/25 Python
20行python代码实现人脸识别
2019/05/05 Python
pandas的to_datetime时间转换使用及学习心得
2019/08/11 Python
Python reversed函数及使用方法解析
2020/03/17 Python
python 画图 图例自由定义方式
2020/04/17 Python
Python Django中间件使用原理及流程分析
2020/06/13 Python
详解python metaclass(元类)
2020/08/13 Python
python如何导出微信公众号文章方法详解
2020/08/31 Python
荷兰鞋子在线:Nelson Schoenen
2017/12/25 全球购物
TCP协议通讯的过程和步骤是什么
2015/10/18 面试题
市场营销工作计划书
2014/05/06 职场文书
教师职位说明书
2014/07/29 职场文书
银行授权委托书格式
2014/10/10 职场文书
企业安全生产检查制度
2015/08/06 职场文书
JavaScript声明变量和数据类型的转换
2022/04/12 Javascript