深思 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 相关文章推荐
复杂检索数据并分页显示的处理方法
Oct 09 PHP
如何写php程序?
Dec 08 PHP
php 获取一个月第一天与最后一天的代码
May 16 PHP
easyui的tabs update正确用法分享
Mar 21 PHP
PHP把JPEG图片转换成Progressive JPEG的方法
Jun 30 PHP
PHP Hash算法:Times33算法代码实例
May 13 PHP
PHP在线打包下载功能示例
Oct 15 PHP
Yii2中datetime类的使用
Dec 17 PHP
php curl批处理实现可控并发异步操作示例
May 09 PHP
PHP实现的AES双向加密解密功能示例【128位】
Sep 03 PHP
PHP切割整数工具类似微信红包金额分配的思路详解
Sep 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
php 方便水印和缩略图的图形类
2009/05/21 PHP
php对二维数组进行排序的简单实例
2013/12/19 PHP
深入理解PHP之OpCode原理详解
2016/06/01 PHP
jQuery DOM操作小结与实例
2010/01/07 Javascript
关闭时刷新父窗口两种方法
2014/05/07 Javascript
深入理解jQuery之防止冒泡事件
2016/05/24 Javascript
AngularJS入门教程一:路由用法初探
2017/05/27 Javascript
Angular.js中下拉框实现渲染html的方法
2017/06/18 Javascript
vue轮播图插件vue-awesome-swiper
2017/11/27 Javascript
浅谈Vue Element中Select下拉框选取值的问题
2018/03/01 Javascript
使用Vue-cli 3.0搭建Vue项目的方法
2018/06/07 Javascript
微信小程序自定义轮播图
2018/11/04 Javascript
详解一个基于套接字实现长连接的express
2019/03/28 Javascript
vue-model实现简易计算器
2020/08/17 Javascript
python使用多线程不断刷新网页的方法
2015/03/31 Python
win与linux系统中python requests 安装
2016/12/04 Python
Python贪吃蛇游戏编写代码
2020/10/26 Python
Python入门之三角函数tan()函数实例详解
2017/11/08 Python
对python中使用requests模块参数编码的不同处理方法
2018/05/18 Python
Flask和Django框架中自定义模型类的表名、父类相关问题分析
2018/07/19 Python
numpy添加新的维度:newaxis的方法
2018/08/02 Python
Python线程下使用锁的技巧分享
2018/09/13 Python
django框架中间件原理与用法详解
2019/12/10 Python
eVitamins日本:在线购买折扣维生素、补品和草药
2019/04/04 全球购物
bonprix荷兰网上商店:便宜的服装、鞋子和家居用品
2020/07/04 全球购物
中兴通讯全球官方网站:ZTE
2020/12/26 全球购物
this关键字的作用
2016/01/30 面试题
工作违纪检讨书
2014/02/17 职场文书
办公室主任职责范本
2014/03/07 职场文书
2014年教师业务学习材料
2014/05/12 职场文书
经济管理专业求职信
2014/06/09 职场文书
农村老人去世追悼词
2015/06/23 职场文书
关于运动会的广播稿
2015/08/19 职场文书
营销策划分析:怎么策划才能更好销量产品?
2019/09/04 职场文书
浅谈Python列表嵌套字典转化的问题
2021/04/07 Python
JavaScript parseInt0.0000005打印5原理解析
2022/07/23 Javascript