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 相关文章推荐
用php写的serv-u的web申请账号的程序
Oct 09 PHP
php str_pad() 将字符串填充成指定长度的字符串
Feb 23 PHP
深入PHP中的HashTable结构详解
Jun 13 PHP
PHP的Socket通信之UDP通信实例
Jul 02 PHP
php版银联支付接口开发简明教程
Oct 14 PHP
利用PHP_XLSXWriter代替PHPExcel的方法示例
Jul 16 PHP
PHP实现的Redis多库选择功能单例类
Jul 27 PHP
PHP实现的mysql操作类【MySQL与MySQLi方式】
Oct 07 PHP
YII分模块加载路由的实现方法
Oct 01 PHP
在laravel框架中实现封装公共方法全局调用
Oct 14 PHP
laravel 解决groupBy时出现的错误 isn't in Group By问题
Oct 17 PHP
解决Laravel使用验证时跳转到首页的问题
Nov 17 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
mysql建立外键
2006/11/25 PHP
wamp下修改mysql访问密码的解决方法
2013/05/07 PHP
PHP对接微信公众平台消息接口开发流程教程
2014/03/25 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(二)
2014/06/23 PHP
ThinkPHP公共配置文件与各自项目中配置文件组合的方法
2014/11/24 PHP
CodeIgniter框架验证码类库文件与用法示例
2017/03/18 PHP
PHP实现数组转JSon和JSon转数组的方法示例
2018/06/14 PHP
js checkbox(复选框) 使用集锦
2009/04/28 Javascript
jQuery中after()方法用法实例
2014/12/25 Javascript
js漂浮广告实现代码
2015/08/15 Javascript
温习Javascript基础语法之词法结构
2016/05/31 Javascript
关于BootStrap modal 在IOS9中不能弹出的解决方法(IOS 9 bootstrap modal ios 9 noticework)
2016/12/14 Javascript
微信小程序 登陆流程详细介绍
2017/01/17 Javascript
脚本div实现拖放功能(两种)
2017/02/13 Javascript
JS仿Base.js实现的继承示例
2017/04/07 Javascript
Spring shiro + bootstrap + jquery.validate 实现登录、注册功能
2017/06/02 jQuery
js对象实例详解(JavaScript对象深度剖析,深度理解js对象)
2017/09/21 Javascript
基于VUE.JS的移动端框架Mint UI的使用
2017/10/11 Javascript
值得收藏的八个常用的js正则表达式
2018/10/19 Javascript
JS实现的Object数组去重功能示例【数组成员为Object对象】
2019/02/01 Javascript
在SSM框架下用laypage和ajax实现分页和数据交互的方法
2019/09/27 Javascript
详解vue父子组件状态同步的最佳方式
2020/09/10 Javascript
[33:39]DOTA2上海特级锦标赛C组小组赛#2 LGD VS Newbee第二局
2016/02/27 DOTA
Python与shell的3种交互方式介绍
2015/04/11 Python
Python3.5面向对象编程图文与实例详解
2019/04/24 Python
Python基于wordcloud及jieba实现中国地图词云图
2020/06/09 Python
python 求两个向量的顺时针夹角操作
2021/03/04 Python
业务员薪酬管理制度
2014/01/15 职场文书
优秀教师感人事迹材料
2014/05/04 职场文书
员工工作自我评价
2014/09/26 职场文书
公司仓管员岗位职责
2015/04/01 职场文书
2016年教师学习教师法心得体会
2016/01/20 职场文书
面试中老生常谈的MySQL问答集锦夯实基础
2022/03/13 MySQL
SQL Server使用导出向导功能
2022/04/08 SQL Server
SQL Server一个字符串拆分多行显示或者多行数据合并成一个字符串
2022/05/25 SQL Server