深思 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 创建标签云函数代码
May 26 PHP
用PHP实现的四则运算表达式计算实现代码
Aug 02 PHP
php的urlencode()URL编码函数浅析
Aug 09 PHP
国外十大最流行的PHP框架排名
Jul 04 PHP
配置php网页显示各种语法错误
Sep 23 PHP
PHP判断JSON对象是否存在的方法(推荐)
Jul 06 PHP
PHP用户验证和标签推荐的简单使用
Oct 31 PHP
PHP中Laravel 关联查询返回错误id的解决方法
Apr 01 PHP
PHP排序算法之基数排序(Radix Sort)实例详解
Apr 21 PHP
PHP封装的mysqli数据库操作类示例
Feb 16 PHP
laravel5.6中的外键约束示例
Oct 23 PHP
PHP程序守护进程化实现方法详解
Jul 16 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
基于xcache的配置与使用详解
2013/06/18 PHP
PHP5.5和之前的版本empty函数的不同之处
2014/06/13 PHP
PHP函数in_array()使用详解
2014/08/20 PHP
PHP使用DOM对XML解析处理操作示例
2019/07/04 PHP
laravel5.2表单验证,并显示错误信息的实例
2019/09/29 PHP
深入浅析JavaScript中的constructor
2016/04/19 Javascript
jquery.serialize() 函数语法及简单实例
2016/07/08 Javascript
AngularJs Injecting Services Into Controllers详解
2016/09/02 Javascript
手机端js和html5刮刮卡效果
2020/09/29 Javascript
树结构之JavaScript
2017/01/24 Javascript
jquery仿苹果的时间/日期选择效果
2017/03/08 Javascript
Vue组件开发之LeanCloud带图形校验码的短信发送功能
2017/11/07 Javascript
ng-events类似ionic中Events的angular全局事件
2018/09/05 Javascript
Node.JS在命令行中检查Chrome浏览器是否安装并打开指定网址
2019/05/21 Javascript
webpack4 SplitChunks实现代码分隔详解
2019/05/23 Javascript
详解vue beforeRouteEnter 异步获取数据给实例问题
2019/08/09 Javascript
vue-form表单验证是否为空值的实例详解
2019/10/29 Javascript
[38:23]完美世界DOTA2联赛循环赛 FTD vs PXG BO2第二场 11.01
2020/11/02 DOTA
查看Python依赖包及其版本号信息的方法
2019/08/13 Python
python如何导出微信公众号文章方法详解
2020/08/31 Python
python实现scrapy爬虫每天定时抓取数据的示例代码
2021/01/27 Python
Python实现钉钉/企业微信自动打卡的示例代码
2021/02/02 Python
python连接手机自动搜集蚂蚁森林能量的实现代码
2021/02/24 Python
css sprite简单实例
2016/05/23 HTML / CSS
What is the purpose of Void class? Void类的作用是什么?
2016/10/31 面试题
高中生学习总结的自我评价范文
2013/10/13 职场文书
2014年公司庆元旦活动方案
2014/03/05 职场文书
中学生英语演讲稿
2014/04/26 职场文书
研修心得体会
2014/09/04 职场文书
2014年教研室工作总结
2014/12/06 职场文书
2015年学校党建工作总结
2015/05/19 职场文书
2015年政府采购工作总结
2015/05/21 职场文书
关于党风廉政建设宣传教育月的活动总结!
2019/08/08 职场文书
导游词之云南丽江古城
2019/09/17 职场文书
python生成可执行exe控制Microsip自动填写号码并拨打功能
2021/06/21 Python
python获取带有返回值的多线程
2022/05/02 Python