深思 PHP 数组遍历的差异(array_diff 的实现)

 更新时间:2008年03月23日 17:46:36   作者:  
还是部门无聊的考题,不过这次考的是 PHP 的能力。题目如下: 给你两个分别有 5000 个元素的数组,计算他们的差集 -- 说白了也就是用 PHP 和你认为最好的算法实现 array_diff 的算法。初次接到这个题目,我发现这非常的简单,于是按照以往的经验“随便”写了一个:
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中的preg_replace和代码执行

    深入研究PHP中的preg_replace和代码执行

    这篇文章主要给大家介绍了关于PHP中preg_replace和代码执行的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-08-08
  • PHP正则匹配到2个字符串之间的内容方法

    PHP正则匹配到2个字符串之间的内容方法

    今天小编就为大家分享一篇PHP正则匹配到2个字符串之间的内容方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-12-12
  • php生成随机验证码图片的示例代码

    php生成随机验证码图片的示例代码

    这篇文章主要介绍了php生成随机验证码图片的示例代码,结合实例形式分析了php生成随机验证码图片的实现方法与相关操作注意事项,文中有详细的代码示例,需要的朋友可以参考下
    2023-09-09
  • 详解PHP的Yii框架中日志的相关配置及使用

    详解PHP的Yii框架中日志的相关配置及使用

    这篇文章主要介绍了PHP的Yii框架中日志的相关配置及使用,包括bug追踪以及数据库查询耗时记录等,需要的朋友可以参考下
    2015-12-12
  • php实现多城市切换特效

    php实现多城市切换特效

    本文给大家主要分享的是在PHP中如何获取用户IP地址、PHP根据IP判断用户所在城市以及PHP根据IP实现城市切换或跳转的问题。
    2015-08-08
  • PHP借助phpmailer发送邮件

    PHP借助phpmailer发送邮件

    phpmailer是一款免费的php邮件发送插件,我们可以利用phpmailer登录到我们指定的邮件然后再利用这个邮件给我们自动发邮件了,这个现在免费的邮箱像163,sina都支持,好了费话不说多了来看看一段phpmainer 163邮件发送邮件吧。
    2015-05-05
  • PHP编程实现的TCP服务端和客户端功能示例

    PHP编程实现的TCP服务端和客户端功能示例

    这篇文章主要介绍了PHP编程实现的TCP服务端和客户端功能,结合实例形式分析了php基于socket实现TCP服务器端与客户端通信功能的相关配置、定义与使用技巧,需要的朋友可以参考下
    2018-04-04
  • php中经典方法实现判断多维数组是否为空

    php中经典方法实现判断多维数组是否为空

    传统的判断数组为空 一般用count或者key 而且多维数组的话很麻烦
    2011-10-10
  • 了解Joomla 这款来自国外的php网站管理系统

    了解Joomla 这款来自国外的php网站管理系统

    joomla在国外很热,就连台湾都有不少站使用joomla,国内就对joomla缺乏了解。大多都使用dedecms或者phpcms等。在这四个月来一直在学习joomla,觉得用它来建站很方便。
    2010-03-03
  • php源代码安装常见错误与解决办法分享

    php源代码安装常见错误与解决办法分享

    这篇文章主要介绍了在linux服务器中通过源代码安装php过程中,经常会遇到的一些问题做个小结,特分享给需要的朋友
    2013-05-05

最新评论