深思 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 相关文章推荐
一个高ai的分页函数和一个url函数
Oct 09 PHP
实用函数3
Nov 08 PHP
PHP 中文乱码解决办法总结分析
Jul 30 PHP
php中的三元运算符使用说明
Jul 03 PHP
ThinkPHP中使用Ueditor富文本编辑器
Sep 02 PHP
在Mac OS上编译安装Nginx+PHP+MariaDB开发环境的教程
Feb 23 PHP
yum命令安装php7和相关扩展
Jul 04 PHP
利用PHP抓取百度阅读的方法示例
Dec 18 PHP
php实现的读取CSV文件函数示例
Feb 07 PHP
Laravel中如何增加自定义全局函数详解
May 09 PHP
laravel 5.4中实现无限级分类的方法示例
Jul 27 PHP
ThinkPHP 在阿里云上的nginx.config配置实例详解
Oct 11 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中的排序函数sort、asort、rsort、krsort、ksort区别分析
2014/08/18 PHP
php生成二维码不保存服务器还有下载功能的实现代码
2018/08/09 PHP
PHP实现本地图片转base64格式并上传
2020/05/29 PHP
统计出现最多的字符次数的js代码
2010/12/03 Javascript
精选的10款用于构建良好易用性网站的jQuery插件
2011/01/23 Javascript
用JQuery实现全选与取消的两种简单方法
2014/02/22 Javascript
jquery实现点击文字可编辑并修改保存至数据库
2014/04/15 Javascript
当滚动条滚动到页面底部自动加载增加内容的js代码
2014/05/13 Javascript
JQuery实现table行折叠效果以JSON做数据源
2014/05/26 Javascript
jQuery定义背景动态切换效果的方法
2015/03/23 Javascript
jquery实现初次打开有动画效果的网页TAB切换代码
2015/09/06 Javascript
整理一下常见的IE错误
2016/11/18 Javascript
解析JavaScript模仿块级作用域
2016/12/29 Javascript
JS表单数据验证的正则表达式(常用)
2017/02/18 Javascript
vue2.0的contextmenu右键弹出菜单的实例代码
2017/07/24 Javascript
微信小程序实现换肤功能
2018/03/14 Javascript
利用Bootstrap Multiselect实现下拉框多选功能
2019/04/08 Javascript
javascript 模块依赖管理的本质深入详解
2020/04/30 Javascript
AngularJs的$http发送POST请求,php无法接收Post的数据问题及解决方案
2020/08/13 Javascript
python基础教程之lambda表达式使用方法
2014/02/12 Python
python实现udp数据报传输的方法
2014/09/26 Python
python基础入门学习笔记(Python环境搭建)
2016/01/13 Python
Python编程实现双链表,栈,队列及二叉树的方法示例
2017/11/01 Python
使用sklearn之LabelEncoder将Label标准化的方法
2018/07/11 Python
python简单实现最大似然估计&amp;scipy库的使用详解
2020/04/15 Python
使用PyQt5实现图片查看器的示例代码
2020/04/21 Python
Python实现快速大文件比较代码解析
2020/09/04 Python
迪卡侬波兰体育用品商店:Decathlon波兰
2020/03/31 全球购物
求职推荐信范文
2013/12/01 职场文书
高一地理教学反思
2014/01/18 职场文书
三年级评语大全
2014/04/23 职场文书
团日活动总结报告
2014/06/25 职场文书
2014年十八届四中全会思想汇报范文
2014/10/17 职场文书
机关党员四风问题个人整改措施
2014/10/26 职场文书
2015年小学美术工作总结
2015/05/25 职场文书
《风筝》教学反思
2016/02/23 职场文书