深思 PHP 数组遍历的差异(array_diff 的实现)


Posted in PHP onMarch 23, 2008

function array_diff($array_1, $array_2) {
    $diff = array();

    foreach ($array_1 as $k => $v1) {
        $flag = false;
        foreach ($array_2 as $v2) {
            if ($flag = ($v1 == $v2)) {
                break;
            }
        }

        if (!$flag) {
            $diff[$k] = $v1;
        }
    }

    return $diff;
}虽然实现是可以的,但是发现这个函数的效率是惨不忍睹。于是我又重新考虑了下,并优化了算法,第二个函数看起来是这个样子的:

function array_diff($array_1, $array_2) {
    foreach ($array_1 as $key => $item) {
        if (in_array($item, $array_2, true)) {
            unset($array_1[$key]);
        }
    }

    return $array_1;
}嗯,这次几乎可以和原 array_diff 函数的速度媲美了。但是还有没有更优化的办法呢?由 ChinaUnix 上的一篇文章(不好意思,作弊了),我发现 PHP 竟然可以这样写:

function array_diff($array_1, $array_2) {
    $array_2 = array_flip($array_2);
    foreach ($array_1 as $key => $item) {
        if (isset($array_2[$item])) {
            unset($array_1[$key]);
        }
     }

    return $array_1;
}这个函数的效率非常的惊人,甚至比原 array_diff 函数的速度都要快。究其原因,我找到了解释:

因为键是进行 HASH 组织的,查找很快;
而 Value 只是由 Key 组织存放,本身没有索引,每次查找都是遍历。总结
这虽然是 PHP 语言的一个小窍门,但在遍历和对比数组的值上,如果需要对比值将其与键反转的确比通常的值对值的比较效率要高得多。

比如,上面的函数二需要调用 in_array 函数需要循环判断是否在函数内;而函数三则仅仅判断这个数组是否存在该键就可以了。加上数组键和值不同的组织索引方式,效率比想象的还高那就非常可以理解了。

附代码

<?php 
function microtime_float() { 
    list($usec, $sec) = explode(" ", microtime()); 
    return ((float)$usec + (float)$sec); 
} function array_diff2($array_1, $array_2) { 
    $diff = array(); 
    foreach ($array_1 as $k => $v1) { 
        $flag = false; 
        foreach ($array_2 as $v2) { 
            if ($flag = ($v1 == $v2)) { 
                break; 
            } 
        } 
        if (!$flag) { 
            $diff[$k] = $v1; 
        } 
    } 
    return $diff; 
} 

function array_diff3($array_1, $array_2) { 
    foreach ($array_1 as $key => $item) { 
        if (in_array($item, $array_2, true)) { 
            unset($array_1[$key]); 
        } 
    } 
    return $array_1; 
} 

function array_diff4($array_1, $array_2) { 
    $array_2 = array_flip($array_2); 
    foreach ($array_1 as $key => $item) { 
        if (isset($array_2[$item])) { 
            unset($array_1[$key]); 
        } 
     } 
    return $array_1; 
} 
////////////////////////////// 
for($i = 0, $ary_1 = array(); $i < 5000; $i++) { 
    $ary_1[] = rand(100, 999); 
} 
for($i = 0, $ary_2 = array(); $i < 5000; $i++) { 
    $ary_2[] = rand(100, 999); 
} 
header("Content-type: text/plain;charset=utf-8"); 
$time_start = microtime_float(); 
array_diff($ary_1, $ary_2); 
echo "函数 array_diff 运行" . (microtime_float() - $time_start) . " 秒\n"; 
$time_start = microtime_float(); 
array_diff2($ary_1, $ary_2); 
echo "函数 array_diff2 运行" . (microtime_float() - $time_start) . " 秒\n"; 
$time_start = microtime_float(); 
array_diff3($ary_1, $ary_2); 
echo "函数 array_diff3 运行" . (microtime_float() - $time_start) . " 秒\n"; 
$time_start = microtime_float(); 
array_diff4($ary_1, $ary_2); 
echo "函数 array_diff4 运行" . (microtime_float() - $time_start) . " 秒\n"; 
?>

PHP 相关文章推荐
sourcesafe管理phpproj文件的补充说明(downmoon)
Apr 11 PHP
php中使用Akismet防止垃圾评论的代码
Jun 10 PHP
php的$_FILES的临时储存文件与回收机制实测过程
Jul 12 PHP
PHP和javascript常用正则表达式及用法实例
Jul 01 PHP
PHP+jQuery 注册模块的改进(三):更新到Smarty3.1
Oct 14 PHP
PHP调用存储过程返回值不一致问题的解决方法分析
Apr 26 PHP
php使用Header函数,PHP_AUTH_PW和PHP_AUTH_USER做用户验证
May 04 PHP
PHP查询附近的人及其距离的实现方法
May 11 PHP
PHP中的函数声明与使用详解
May 27 PHP
浅谈PHP发送HTTP请求的几种方式
Jul 25 PHP
详解php与ethereum客户端交互
Apr 28 PHP
ThinkPhP+Apache+PHPstorm整合框架流程图解
Nov 23 PHP
附件名前加网站名
Mar 23 #PHP
由php if 想到的些问题
Mar 22 #PHP
php实现mysql数据库备份类
Mar 20 #PHP
php 常用字符串函数总结
Mar 15 #PHP
php str_replace的替换漏洞
Mar 15 #PHP
PHP执行速率优化技巧小结
Mar 15 #PHP
请php正则走开
Mar 15 #PHP
You might like
PHP下打开URL地址的几种方法小结
2010/05/16 PHP
PHP如何解决网站大流量与高并发的问题
2011/06/25 PHP
深入解析PHP内存管理之谁动了我的内存
2013/06/20 PHP
php中如何使对象可以像数组一样进行foreach循环
2013/08/09 PHP
如何让thinkphp在模型中自动完成session赋值小教程
2014/09/05 PHP
Zend Framework框架中实现Ajax的方法示例
2017/06/27 PHP
基于jquery &amp; json的省市区联动代码
2012/06/26 Javascript
javascript 文件的同步加载与异步加载实现原理
2012/12/13 Javascript
js 将json字符串转换为json对象的方法解析
2013/11/13 Javascript
jquery清空表单数据示例分享
2014/02/13 Javascript
兼容最新firefox、chrome和IE的javascript图片预览实现代码
2014/08/08 Javascript
整理AngularJS中的一些常用指令
2015/06/16 Javascript
纯javascript模仿微信打飞机小游戏
2015/08/20 Javascript
json数据处理及数据绑定
2017/01/25 Javascript
使用bootstraptable插件实现表格记录的查询、分页、排序操作
2017/08/06 Javascript
canvas轨迹回放功能实现
2017/12/20 Javascript
JS中利用FileReader实现上传图片前本地预览功能
2018/03/02 Javascript
vue.js在标签属性中插入变量参数的方法
2018/03/06 Javascript
微信小程序实现展示评分结果功能
2019/02/15 Javascript
ES6模板字符串和标签模板的应用实例分析
2019/06/25 Javascript
vue移动端模态框(可传参)的实现
2019/11/20 Javascript
jQuery操作元素追加内容示例
2020/01/10 jQuery
vue项目配置使用flow类型检查的步骤
2020/03/18 Javascript
编写Python CGI脚本的教程
2015/06/29 Python
Python的迭代器和生成器
2015/07/29 Python
解决python selenium3启动不了firefox的问题
2018/10/13 Python
python爬虫模拟浏览器访问-User-Agent过程解析
2019/12/28 Python
巴西男士胡须和头发护理产品商店:Beard
2017/11/13 全球购物
新加坡网上化妆品店:Best Buy World
2018/05/18 全球购物
高性能装备提升营地:Kammok
2019/02/27 全球购物
简短证婚人证婚词
2014/01/09 职场文书
化学专业毕业生求职信
2014/07/28 职场文书
2014年公务员工作总结
2014/11/18 职场文书
2015年小学语文工作总结
2015/05/25 职场文书
廉洁自律准则学习心得体会
2016/01/13 职场文书
SQL bool盲注和时间盲注详解
2022/07/23 SQL Server