深思 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 强制下载文件代码
Oct 24 PHP
用PHP读取和编写XML DOM的实现代码
Feb 03 PHP
10个实用的PHP代码片段
Sep 02 PHP
php合并js请求的例子
Nov 01 PHP
PHP获取二维数组中某一列的值集合
Dec 25 PHP
Yii2 输出xml格式数据的方法
May 03 PHP
PHP数据的提交与过滤基本操作实例详解
Nov 11 PHP
Zend Framework处理Json数据方法详解
Dec 09 PHP
CI(CodeIgniter)框架视图中加载视图的方法
Mar 24 PHP
laravel5.4利用163邮箱发送邮件的步骤详解
Sep 22 PHP
php实现生成带二维码图片并强制下载功能
Feb 24 PHP
PHP读取文件,解决中文乱码UTF-8的方法分析
Jan 22 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生成带有雪花背景的验证码
2008/09/28 PHP
解析isset与is_null的区别
2013/08/09 PHP
php带抄送和密件抄送的邮件发送方法
2015/03/20 PHP
php给图片添加文字水印方法汇总
2015/08/27 PHP
PHP扩展迁移为PHP7扩展兼容性问题记录
2016/02/15 PHP
PHP合并数组的2种方法小结
2016/11/24 PHP
ThinkPHP3.2框架使用addAll()批量插入数据的方法
2017/03/16 PHP
phpStudy配置多站点多域名方法及遇到的403错误解决方法
2017/10/19 PHP
精通JavaScript 纠正 cleanWhitespace函数
2010/03/11 Javascript
JavaScript 学习笔记二 字符串拼接
2010/03/28 Javascript
JQuery autocomplete 使用手册
2010/04/01 Javascript
AJAX分页的代码(后台asp.net)
2011/02/14 Javascript
如何确保JavaScript的执行顺序 之jQuery.html深度分析
2011/03/03 Javascript
jQuery前台数据获取实现代码
2011/03/16 Javascript
uploadify 3.0 详细使用说明
2012/06/18 Javascript
浅谈javascript的原型继承
2012/07/25 Javascript
如何正确使用javascript 来进行我们的程序开发
2014/06/23 Javascript
javascript实现获取cookie过期时间的变通方法
2014/08/14 Javascript
jQuery实现数字加减效果汇总
2014/12/16 Javascript
Javascript核心读书有感之类型、值和变量
2015/02/11 Javascript
javascript 动态样式添加的简单实现
2016/10/11 Javascript
BOM之navigator对象和用户代理检测
2017/02/10 Javascript
node.js的exports、module.exports与ES6的export、export default深入详解
2017/10/26 Javascript
详解node字体压缩插件font-spider的用法
2018/09/28 Javascript
LayUi数据表格自定义赋值方式
2019/10/26 Javascript
对python pandas 画移动平均线的方法详解
2018/11/28 Python
Pytorch自定义Dataset和DataLoader去除不存在和空数据的操作
2021/03/03 Python
CSS3中box-shadow的用法介绍
2015/07/15 HTML / CSS
详解如何使用rem或viewport进行移动端适配
2020/08/14 HTML / CSS
StubHub巴西:购买和出售您的门票
2016/07/22 全球购物
一加手机美国官方网站:OnePlus美国
2019/09/19 全球购物
三星俄罗斯授权在线商店:Samsung俄罗斯
2019/09/28 全球购物
工程地质勘察专业大学生求职信
2013/10/13 职场文书
安全大检查实施方案
2014/02/22 职场文书
农村婚礼司仪主持词
2015/06/29 职场文书
七年级思品教学反思
2016/02/20 职场文书