深思 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 相关文章推荐
PHP去除数组中重复的元素并按键名排序函数
Aug 18 PHP
Windows下安装Memcached的步骤说明
Apr 25 PHP
php后台多用户权限组思路与实现程序代码分享
Feb 13 PHP
利用PHP扩展vld查看PHP opcode操作步骤
Mar 04 PHP
php利用cookie实现自动登录的方法
Dec 10 PHP
PHP实现过滤掉非汉字字符只保留中文字符
Jun 04 PHP
PHP计算当前坐标3公里内4个角落的最大最小经纬度实例
Feb 26 PHP
PHP编写学校网站上新生注册登陆程序的实例分享
Mar 21 PHP
功能强大的php分页函数
Jul 20 PHP
PHP实现动态获取函数参数的方法示例
Apr 02 PHP
laravel-admin表单提交隐藏一些数据,回调时获取数据的方法
Oct 08 PHP
Laravel 框架返回状态拦截代码
Oct 18 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
一个域名查询的程序
2006/10/09 PHP
如何批量替换相对地址为绝对地址(利用bat批处理实现)
2013/05/27 PHP
php生成图片缩略图的方法
2015/04/07 PHP
深入理解PHP之OpCode原理详解
2016/06/01 PHP
php实现的读取CSV文件函数示例
2017/02/07 PHP
PHP中的函数声明与使用详解
2017/05/27 PHP
php7安装mongoDB扩展的方法分析
2017/08/02 PHP
PHP的mysqli_stat()函数讲解
2019/01/23 PHP
Nigma vs Alliance BO5 第二场2.14
2021/03/10 DOTA
javascript 设置某DIV区域内的checkbox复选框
2009/11/30 Javascript
Firefox中beforeunload事件的实现缺陷浅析
2012/05/03 Javascript
js网页中的(运行代码)功能实现思路
2013/02/04 Javascript
关于jQuery中.attr()和.prop()的问题探讨
2013/09/06 Javascript
JS版的date函数(和PHP的date函数一样)
2014/05/12 Javascript
教你如何自定义百度分享插件以及bshare分享插件的分享按钮
2014/06/20 Javascript
Node.js的特点和应用场景介绍
2014/11/04 Javascript
jQuery实现仿QQ空间装扮预览图片的鼠标提示效果代码
2015/10/30 Javascript
Javascript实现检测客户端类型代码封包
2015/12/03 Javascript
jQuery实现的购物车物品数量加减功能代码
2016/11/16 Javascript
js图片轮播手动切换特效
2017/01/12 Javascript
jQuery无刷新上传之uploadify简单代码
2017/01/17 Javascript
css和js实现弹出登录居中界面完整代码
2017/11/26 Javascript
解决vue-router进行build无法正常显示路由页面的问题
2018/03/06 Javascript
Vue组件间数据传递的方式(3种)
2020/07/13 Javascript
简单掌握Python的Collections模块中counter结构的用法
2016/07/07 Python
Window10下python3.7 安装与卸载教程图解
2019/09/30 Python
python  ceiling divide 除法向上取整(或小数向上取整)的实例
2019/12/27 Python
python logging通过json文件配置的步骤
2020/04/27 Python
html5 canvas绘制网络字体的常用方法
2019/08/26 HTML / CSS
The North Face官方旗舰店:美国著名户外品牌
2020/09/28 全球购物
简单而又朴实的个人求职信分享
2013/12/12 职场文书
心理咨询承诺书
2014/05/20 职场文书
读书月活动方案
2014/05/22 职场文书
娱乐节目策划方案
2014/06/10 职场文书
校长新学期致辞
2015/07/30 职场文书
2015团员个人年度总结
2015/11/24 职场文书