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日历程序
Dec 06 PHP
封装一个PDO数据库操作类代码
Sep 09 PHP
PHP 图像尺寸调整代码
May 26 PHP
PHP 循环列出目录内容的函数代码
May 26 PHP
PHP中使用crypt()实现用户身份验证的代码
Sep 05 PHP
使用PHP静态变量当缓存的方法
Nov 13 PHP
destoon公司主页模板风格的添加方法
Jun 20 PHP
php实现图片文件与下载文件防盗链的方法
Nov 03 PHP
PHP、Python和Javascript的装饰器模式对比
Feb 03 PHP
laravel中命名路由的使用方法
Feb 24 PHP
PHP判断一个数组是另一个数组子集的方法详解
Jul 31 PHP
laravel多条件查询方法(and,or嵌套查询)
Oct 09 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
php实现登陆模块功能示例
2016/10/20 PHP
PHP生成加减算法方式的验证码实例
2018/03/12 PHP
一个加密JavaScript的开源工具PACKER2.0.2
2006/11/04 Javascript
Ext.FormPanel 提交和 Ext.Ajax.request 异步提交函数的区别
2009/11/12 Javascript
解析window.open的使用方法总结
2013/06/19 Javascript
JavaScript中圆括号()和方括号[]的特殊用法疑问解答
2013/08/06 Javascript
jQuery 属性选择器element[herf*='value']使用示例
2013/10/20 Javascript
js实现日期级联效果
2014/01/23 Javascript
js实现二级菜单渐隐显示
2015/11/03 Javascript
javascript实现无缝上下滚动特效
2015/12/16 Javascript
jQuery+css实现的时钟效果(兼容各浏览器)
2016/01/27 Javascript
JS+HTML5实现的前端购物车功能插件实例【附demo源码下载】
2016/10/17 Javascript
jQuery File Upload文件上传插件使用详解
2016/12/06 Javascript
VUE前端cookie简单操作
2017/10/17 Javascript
为什么要使用Vuex的介绍
2019/01/19 Javascript
vue-router结合vuex实现用户权限控制功能
2019/11/14 Javascript
Vue自动构建发布脚本的方法示例
2020/07/24 Javascript
[03:26]《DAC最前线》之EG经理自述DOTA2经历
2015/02/02 DOTA
PyQt 线程类 QThread使用详解
2017/07/16 Python
python 3.0 模拟用户登录功能并实现三次错误锁定
2017/11/01 Python
Python排序搜索基本算法之插入排序实例分析
2017/12/11 Python
pandas 选取行和列数据的方法详解
2019/08/08 Python
python_matplotlib改变横坐标和纵坐标上的刻度(ticks)方式
2020/05/16 Python
python try...finally...的实现方法
2020/11/25 Python
python之pygame模块实现飞机大战完整代码
2020/11/29 Python
css3 伪类选择器快速复习小结
2019/09/10 HTML / CSS
创建文明学校实施方案
2014/03/11 职场文书
副职竞争上岗演讲稿
2014/05/12 职场文书
党建工作经验交流材料
2014/05/25 职场文书
法定代表人授权委托书
2014/09/19 职场文书
三严三实学习心得体会
2014/10/13 职场文书
体育活动总结
2015/02/04 职场文书
公司老总年会致辞
2015/07/30 职场文书
教师节祝酒词
2015/08/11 职场文书
《杜鹃的婚约》OP主题曲「凸凹」无字幕影像公开
2022/04/08 日漫
Android实现获取短信验证码并自动填充
2023/05/21 Java/Android