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 相关文章推荐
DOMXML函数笔记
Oct 09 PHP
使用PHPMYADMIN操作mysql数据库添加新用户和数据库的方法
Apr 02 PHP
探讨:array2xml和xml2array以及xml与array的互相转化
Jun 24 PHP
解析php多线程下载远程多个文件
Jun 25 PHP
php foreach循环中使用引用的问题
Nov 06 PHP
PHP获取MAC地址的具体实例
Dec 13 PHP
php实现telnet功能示例
Apr 08 PHP
php结合md5的加密解密算法实例
Sep 30 PHP
PHP5.5安装PHPRedis扩展及连接测试方法
Jan 22 PHP
laravel dingo API返回自定义错误信息的实例
Sep 29 PHP
php实现银联商务公众号+服务窗支付的示例代码
Oct 12 PHP
php libevent 功能与使用方法详解
Mar 04 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
用libTemplate实现静态网页的生成
2006/10/09 PHP
php 友好URL的实现(吐血推荐)
2008/10/04 PHP
探讨如何在PHP开启gzip页面压缩实例
2013/06/09 PHP
PHP中怎样防止SQL注入分析
2014/10/23 PHP
php简单实现批量上传图片的方法
2016/05/09 PHP
利用PHP访问MySql数据库的逻辑操作以及增删改查的实例讲解
2017/08/30 PHP
Laravel模糊查询区分大小写的实例
2019/09/29 PHP
DHTML 中的绝对定位
2006/11/26 Javascript
Javascript 获取滚动条位置等信息的函数
2009/09/08 Javascript
客户端 使用XML DOM加载json数据的方法
2010/09/28 Javascript
js检测浏览器版本、核心、是否移动端示例
2014/04/24 Javascript
可以浮动某个物体的jquery控件用法实例
2015/07/24 Javascript
详解js图片轮播效果实现原理
2015/12/17 Javascript
js仿百度登录页实现拖动窗口效果
2016/03/11 Javascript
AngularJS在IE下取数据总是缓存问题的解决方法
2016/08/05 Javascript
jQuery设置和获取select、checkbox、radio的选中值方法
2017/01/01 Javascript
详解jQuery中的getAll()和cleanData()
2019/04/15 jQuery
JavaScript 继承 封装 多态实现及原理详解
2019/07/29 Javascript
python三元运算符实现方法
2013/12/17 Python
Python内置函数dir详解
2015/04/14 Python
利用Django内置的认证视图实现用户密码重置功能详解
2017/11/24 Python
Python Json模块中dumps、loads、dump、load函数介绍
2018/05/15 Python
对pandas中时间窗函数rolling的使用详解
2018/11/28 Python
Python 支付整合开发包的实现
2019/01/23 Python
python实现证件照换底功能
2019/08/20 Python
对YOLOv3模型调用时候的python接口详解
2019/08/26 Python
Python 将json序列化后的字符串转换成字典(推荐)
2020/01/06 Python
Iconfont(矢量图标)+iconmoon(图标svg互转)配合javascript实现社交分享系统
2020/04/21 Python
win10安装python3.6的常见问题
2020/07/01 Python
selenium+headless chrome爬虫的实现示例
2021/01/08 Python
微信浏览器左上角返回按钮拦截功能
2017/11/21 HTML / CSS
SQL注入攻击的种类有哪些
2013/12/30 面试题
幼教求职信
2014/03/12 职场文书
主办会计岗位职责
2014/03/13 职场文书
2016年大学迎新晚会工作总结
2015/10/15 职场文书
导游词之贵州织金洞
2019/10/12 职场文书