深思 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开发GUI
Oct 09 PHP
也谈php网站在线人数统计
Apr 09 PHP
shopex中集成的站长统计功能的代码简单分析
Aug 11 PHP
Fine Uploader文件上传组件应用介绍
Jan 06 PHP
基于php socket(fsockopen)的应用实例分析
Jun 02 PHP
学习php过程中的一些注意点的总结
Oct 25 PHP
php 使用GD库为页面增加水印示例代码
Mar 24 PHP
推荐一款PHP+jQuery制作的列表分页的功能模块
Oct 14 PHP
php5.3后静态绑定用法详解
Nov 11 PHP
php面向对象的用户登录身份验证
Jun 08 PHP
php基于 swoole 实现的异步处理任务功能示例
Aug 13 PHP
php操作redis数据库常见方法实例总结
Feb 20 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使用simplexml_load_file加载XML文件并显示XML的方法
2015/03/19 PHP
详解WordPress中创建和添加过滤器的相关PHP函数
2015/12/29 PHP
做网页的一些技巧(续)
2007/02/01 Javascript
用JQuery 实现的自定义对话框
2007/03/24 Javascript
谷歌浏览器 insertCell与appendChild的区别
2009/02/12 Javascript
JQuery获取元素文档大小、偏移和位置和滚动条位置的方法集合
2010/01/12 Javascript
Javascript基础知识(二)事件
2014/09/29 Javascript
JS+CSS实现大气清新的滑动菜单效果代码
2015/10/22 Javascript
浅谈JS使用[ ]来访问对象属性
2016/09/21 Javascript
js提示框替代系统alert,自动关闭alert对话框的实现方法
2016/11/07 Javascript
原生JS获取元素的位置与尺寸实现方法
2017/10/18 Javascript
利用Console来Debug的10个高级技巧汇总
2018/03/26 Javascript
jQuery实现表格的增、删、改操作示例
2019/01/27 jQuery
JavaScript数组去重的方法总结【12种方法,号称史上最全】
2019/02/28 Javascript
vue里如何主动销毁keep-alive缓存的组件
2019/03/21 Javascript
微信小程序实现可拖动悬浮图标(包括按钮角标的实现)
2020/12/29 Javascript
Python中import导入上一级目录模块及循环import问题的解决
2016/06/04 Python
Python脚本处理空格的方法
2016/08/08 Python
Python生成8位随机字符串的方法分析
2017/12/05 Python
python 动态生成变量名以及动态获取变量的变量名方法
2019/01/20 Python
代码实例讲解python3的编码问题
2019/07/08 Python
Python hashlib常见摘要算法详解
2020/01/13 Python
python re模块匹配贪婪和非贪婪模式详解
2020/02/11 Python
Python如何省略括号方法详解
2020/03/21 Python
Python GUI编程学习笔记之tkinter界面布局显示详解
2020/03/30 Python
Pandas直接读取sql脚本的方法
2021/01/21 Python
瑞贝卡·泰勒官方网站:Rebecca Taylor
2016/09/24 全球购物
Java Servlet API中forward() 与redirect()的区别
2014/04/20 面试题
五年级科学教学反思
2014/02/05 职场文书
简单租房协议书
2014/04/09 职场文书
3的组成教学反思
2014/04/30 职场文书
教师党的群众路线教育实践活动个人整改措施
2014/11/04 职场文书
党员思想汇报材料
2014/12/19 职场文书
2015年教务主任工作总结
2015/07/22 职场文书
创业计划书之健康营养产业
2019/10/15 职场文书
PyCharm配置KBEngine快速处理代码提示冲突、配置命令问题
2021/04/03 Python