深思 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 相关文章推荐
深入了解php4(2)--重访过去
Oct 09 PHP
检查url链接是否已经有参数的php代码 添加 ? 或 &amp;
Feb 09 PHP
ie与session丢失(新窗口cookie丢失)实测及解决方案
Jul 15 PHP
mac下Apache + MySql + PHP搭建网站开发环境
Jun 02 PHP
ThinkPHP CURD方法之table方法详解
Jun 18 PHP
destoon安全设置中需要设置可写权限的目录及文件
Jun 21 PHP
php随机获取金山词霸每日一句的方法
Jul 09 PHP
PHP简单处理表单输入的特殊字符的方法
Feb 03 PHP
PHP删除字符串中非字母数字字符方法总结
Jan 20 PHP
PHP实现统计代码行数小工具
Sep 19 PHP
PHP保存Base64图片base64_decode的问题整理
Nov 04 PHP
WordPress免插件实现面包屑导航的示例代码
Aug 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模板原理讲解
2013/11/13 PHP
几道坑人的PHP面试题 试试看看你会不会也中招
2014/08/19 PHP
PHP中对数组的一些常用的增、删、插操作函数总结
2015/11/27 PHP
PHP简单判断iPhone、iPad、Android及PC设备的方法
2016/10/11 PHP
Alliance vs AM BO3 第二场2.13
2021/03/10 DOTA
jQuery验证Checkbox是否选中的代码 推荐
2011/09/04 Javascript
javascript针对DOM的应用实例(一)
2012/04/15 Javascript
jQuery 瀑布流 绝对定位布局(二)(延迟AJAX加载图片)
2012/05/23 Javascript
js确认删除对话框效果的示例代码
2014/02/20 Javascript
JS获取文本框,下拉框,单选框的值的简单实例
2014/02/26 Javascript
基于编写jQuery的无缝滚动插件
2014/08/02 Javascript
js实现可得到不同颜色值的颜色选择器实例
2015/02/28 Javascript
JS使用parseInt解析数字实现求和的方法
2015/08/05 Javascript
JS实现网页上随滚动条滚动的层效果代码
2015/11/04 Javascript
详解Angularjs中的依赖注入
2016/03/11 Javascript
jQuery过滤选择器经典应用
2016/08/18 Javascript
基于AngularJS前端云组件最佳实践
2016/10/20 Javascript
canvas 绘制圆形时钟
2017/02/22 Javascript
除Console.log()外更多的Javascript调试命令
2018/01/24 Javascript
浅析微信扫码登录原理(小结)
2018/10/29 Javascript
Vue使用Canvas绘制图片、矩形、线条、文字,下载图片
2019/04/26 Javascript
jQuery实现简单三级联动效果
2020/09/05 jQuery
跟老齐学Python之深入变量和引用对象
2014/09/24 Python
Python批量删除只保留最近几天table的代码实例
2019/04/01 Python
通过实例了解python property属性
2019/11/01 Python
Python实现RGB与HSI颜色空间的互换方式
2019/11/27 Python
python中plt.imshow与cv2.imshow显示颜色问题
2020/07/16 Python
python 三种方法提取pdf中的图片
2021/02/07 Python
国际鲜花速递专家:Floraqueen
2016/11/24 全球购物
美国踏板车和轻便摩托车销售网站:Mega Motor Madness
2020/02/26 全球购物
汉米尔顿手表官网:Hamilton
2020/09/13 全球购物
Lookfantastic阿联酋官网:英国知名美妆护肤购物网站
2020/05/26 全球购物
机电一体化应届生求职信
2014/08/09 职场文书
活动总结书怎么写
2015/05/11 职场文书
送给火锅店的创意营销方案!
2019/07/08 职场文书
什么是Python装饰器?如何定义和使用?
2022/04/11 Python