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 中英文混合排版中处理字符串常用的函数
Apr 12 PHP
php 格式化数字的时候注意数字的范围
Apr 13 PHP
php摘要生成函数(无乱码)
Feb 04 PHP
ThinkPHP3.2.2的插件控制器功能简述
Jul 09 PHP
PHP中使用Imagick读取pdf并生成png缩略图实例
Jan 21 PHP
浅谈PDO的rowCount函数
Jun 18 PHP
详解php的socket通信
Aug 11 PHP
使用PHP实现生成HTML静态页面
Nov 18 PHP
详解WordPress中创建和添加过滤器的相关PHP函数
Dec 29 PHP
php实现URL加密解密的方法
Nov 17 PHP
Laravel中log无法写入问题的解决
Jun 17 PHP
PHP设计模式之工厂模式详解
Oct 24 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
从零开始学YII2框架(一)通过Composer安装Yii2框架
2014/08/20 PHP
Zend Framework教程之Zend_Registry对象用法分析
2016/03/22 PHP
JavaScript实现页面滚动图片加载(仿lazyload效果)
2011/07/22 Javascript
JavaScript中window.showModalDialog()用法详解
2014/12/18 Javascript
js/jquery判断浏览器类型的方法小结
2015/05/12 Javascript
使用javaScript动态加载Js文件和Css文件
2015/10/24 Javascript
基于JavaScript实现Json数据根据某个字段进行排序
2015/11/24 Javascript
checkbox批量选中,获取选中项的值的简单实例
2016/06/28 Javascript
Javascript中indexOf()和lastIndexOf应用方法实例
2016/08/24 Javascript
jq给页面添加覆盖层遮罩的实例
2017/02/16 Javascript
JS中IP地址与整数相互转换的实现代码
2017/04/10 Javascript
基于vue v-for 循环复选框-默认勾选第一个的实现方法
2018/03/03 Javascript
微信小程序动画(Animation)的实现及执行步骤
2018/10/28 Javascript
javascript面向对象三大特征之封装实例详解
2019/07/24 Javascript
解决layui checkbox 提交多个值的问题
2019/09/02 Javascript
Vue实现PC端靠边悬浮球的代码
2020/05/09 Javascript
用Python从零实现贝叶斯分类器的机器学习的教程
2015/03/31 Python
scrapy爬虫完整实例
2018/01/25 Python
Django实现发送邮件功能
2019/07/18 Python
Mac安装python3的方法步骤
2019/08/09 Python
浅谈Pytorch中的自动求导函数backward()所需参数的含义
2020/02/29 Python
如何基于Python爬取隐秘的角落评论
2020/07/02 Python
python 视频下载神器(you-get)的具体使用
2021/01/06 Python
Python爬虫爬取微博热搜保存为 Markdown 文件的源码
2021/02/22 Python
StubHub澳大利亚:购买或出售您的门票
2019/08/01 全球购物
大码女装:Ulla Popken
2019/08/06 全球购物
英国鞋网:Rubber Sole
2020/03/03 全球购物
vue+django实现下载文件的示例
2021/03/24 Vue.js
运动会通讯稿100字
2014/01/31 职场文书
如何写自我鉴定
2014/03/19 职场文书
祖国在我心中演讲稿600字
2014/09/23 职场文书
婚礼新人答谢词
2015/01/04 职场文书
三八妇女节新闻稿
2015/07/17 职场文书
同学会感言
2015/07/30 职场文书
react 项目中引入图片的几种方式
2021/06/02 Javascript
mysql 乱码 字符集latin1转UTF8
2022/04/19 MySQL