深思 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 快速生成 Flash 动画的方法
Mar 06 PHP
让PHP开发者事半功倍的十大技巧小结
Apr 20 PHP
PHP zlib扩展实现页面GZIP压缩输出
Jun 17 PHP
用PHP将数据导入到Foxmail的实现代码
Sep 05 PHP
防止本地用户用fsockopen DDOS攻击对策
Nov 02 PHP
php smarty模板引擎的6个小技巧
Apr 24 PHP
PHP获取当前日期和时间及格式化方法参数
May 11 PHP
PHP实现C#山寨ArrayList的方法
Jul 16 PHP
功能强大的PHP POST提交数据类
Jul 15 PHP
浅析PHP开发规范
Feb 05 PHP
yii2安装详细流程
May 23 PHP
laravel实现前后台路由分离的方法
Oct 13 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 array_pop()数组函数将数组最后一个单元弹出(出栈)
2011/07/12 PHP
PHP弹出对话框技巧详细解读
2015/09/26 PHP
Laravel框架实现利用中间件进行操作日志记录功能
2018/06/06 PHP
laravel 事件/监听器实例代码
2019/04/12 PHP
asp javascript 实现关闭窗口时保存数据的办法
2007/11/24 Javascript
一段利用WSH获取登录时间的jscript代码
2008/05/11 Javascript
jQuery选择没有colspan属性的td的代码
2010/07/06 Javascript
基于jquery的分页控件(C#)
2011/01/06 Javascript
Json字符串转换为JS对象的高效方法实例
2013/05/01 Javascript
jquery实现在页面加载的时自动为日期插件添加当前日期
2014/08/20 Javascript
jQuery实现图片轮播特效代码分享
2015/09/15 Javascript
如何解决IONIC页面底部被遮住无法向上滚动问题
2016/09/06 Javascript
JavaScript严格模式详解
2017/01/16 Javascript
jquery中绑定事件的异同
2017/02/28 Javascript
详解基于webpack和vue.js搭建开发环境
2017/04/05 Javascript
vue中路由参数传递可能会遇到的坑
2017/12/07 Javascript
jQuery UI实现动画效果代码分享
2018/08/19 jQuery
Vue模拟数据,实现路由进入商品详情页面的示例
2018/08/31 Javascript
JavaScript函数的4种调用方法实例分析
2019/03/05 Javascript
Webpack 4如何动态切割JS注入文件名详解
2019/07/09 Javascript
python爬虫_自动获取seebug的poc实例
2017/08/05 Python
利用python画出折线图
2018/07/26 Python
在python带权重的列表中随机取值的方法
2019/01/23 Python
Python之修改图片像素值的方法
2019/07/03 Python
Selenium向iframe富文本框输入内容过程图解
2020/04/10 Python
Keras保存模型并载入模型继续训练的实现
2021/02/20 Python
使用分层画布来优化HTML5渲染的教程
2015/05/08 HTML / CSS
印度最大的时尚购物网站:Myntra
2018/09/13 全球购物
报到证丢失证明
2014/01/11 职场文书
校园安全检查制度
2014/02/03 职场文书
大学军训感言200字
2014/02/26 职场文书
2014年五一活动策划方案
2014/03/15 职场文书
毕业欢送会致辞
2015/07/29 职场文书
分析mysql中一条SQL查询语句是如何执行的
2021/06/21 MySQL
怎么禁用Windows 11快照布局? win11不使用快照布局的技巧
2021/11/21 数码科技
MySQL数据库 安全管理
2022/05/06 MySQL