深思 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实现多服务器session共享之NFS共享的方法
Mar 16 PHP
php中cookie的作用域
Mar 27 PHP
探讨Smarty中如何获取数组的长度以及smarty调用php函数的详解
Jun 20 PHP
php 获取今日、昨日、上周、本月的起始时间戳和结束时间戳的方法
Sep 28 PHP
PHP生成Gif图片验证码
Oct 27 PHP
curl实现站外采集的方法和技巧
Jan 31 PHP
PHP实现更新中间关联表数据的两种方法
Sep 01 PHP
php常见的魔术方法详解
Dec 25 PHP
php实现微信公众号无限群发
Oct 11 PHP
PHP实现的mongoDB数据库操作类完整实例
Apr 10 PHP
PHP中关于php.ini参数优化详解
Feb 28 PHP
tp5.1框架数据库子查询操作实例分析
May 26 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 mb_convert_encoding 获取字符串编码类型实现代码
2009/04/26 PHP
PHP 第一节 php简介
2012/04/28 PHP
浅析PHP的ASCII码转换类
2013/07/05 PHP
php采用file_get_contents代替使用curl实例
2014/11/07 PHP
PHP中的魔术方法总结和使用实例
2015/05/11 PHP
Thinkphp事务操作实例(推荐)
2017/04/01 PHP
简单的php购物车代码
2020/06/05 PHP
Laravel登录失败次数限制的实现方法
2020/08/26 PHP
JavaScript中的对象化编程
2008/01/16 Javascript
css与javascript跨浏览器兼容性总结
2014/09/15 Javascript
JavaScript 学习笔记之操作符
2015/01/14 Javascript
yii form 表单提交之前JS在提交按钮的验证方法
2017/03/15 Javascript
Bootstrap下拉菜单Dropdowns的实现代码
2017/03/17 Javascript
jQuery插件开发发送短信倒计时功能代码
2017/05/09 jQuery
Node.js中 __dirname 的使用介绍
2017/06/19 Javascript
Mui使用jquery并且使用点击跳转新窗口的实例
2017/08/19 jQuery
AngularJS实现的select二级联动下拉菜单功能示例
2017/10/25 Javascript
微信小程序页面生命周期详解
2018/01/31 Javascript
JQuery通过后台获取数据遍历到前台的方法
2018/08/13 jQuery
实例详解带参数的 npm script
2019/05/28 Javascript
JS面向对象编程实现的拖拽功能案例详解
2020/03/03 Javascript
Postman动态获取返回值过程详解
2020/06/30 Javascript
python fabric使用笔记
2015/05/09 Python
python实现kmp算法的实例代码
2019/04/03 Python
Python 3 使用Pillow生成漂亮的分形树图片
2019/12/24 Python
Tensorflow 实现释放内存
2020/02/03 Python
吉力贝官方网站:Jelly Belly
2019/03/11 全球购物
总经理驾驶员岗位职责
2013/12/04 职场文书
幼儿园门卫制度
2014/01/29 职场文书
护士感人事迹
2014/05/01 职场文书
环保公益策划方案
2014/08/15 职场文书
2014年节能降耗工作总结
2014/12/11 职场文书
放射科岗位职责
2015/02/14 职场文书
活动新闻稿范文
2015/07/17 职场文书
Python OpenCV之常用滤波器使用详解
2022/04/07 Python
使用Apache Camel表达REST服务的方法
2022/06/10 Servers