深思 PHP 數組遍歷的差異(array_diff 的實現)
更新時間:2008年03月23日 17:46:36 作者:
還是部門無聊的考題,不過這次考的是 PHP 的能力。題目如下:
給你兩個分別有 5000 個元素的數組,計算他們的差集
-- 說白了也就是用 PHP 和你認為最好的算法實現 array_diff 的算法。初次接到這個題目,我發(fā)現這非常的簡單,于是按照以往的經驗“隨便”寫了一個:
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;
}雖然實現是可以的,但是發(fā)現這個函數的效率是慘不忍睹。于是我又重新考慮了下,并優(yōu)化了算法,第二個函數看起來是這個樣子的:
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 函數的速度媲美了。但是還有沒有更優(yōu)化的辦法呢?由 ChinaUnix 上的一篇文章(不好意思,作弊了),我發(fā)現 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 函數需要循環(huán)判斷是否在函數內;而函數三則僅僅判斷這個數組是否存在該鍵就可以了。加上數組鍵和值不同的組織索引方式,效率比想象的還高那就非??梢岳斫饬恕?
附代碼
<?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";
?>
$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;
}雖然實現是可以的,但是發(fā)現這個函數的效率是慘不忍睹。于是我又重新考慮了下,并優(yōu)化了算法,第二個函數看起來是這個樣子的:
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 函數的速度媲美了。但是還有沒有更優(yōu)化的辦法呢?由 ChinaUnix 上的一篇文章(不好意思,作弊了),我發(fā)現 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 函數需要循環(huán)判斷是否在函數內;而函數三則僅僅判斷這個數組是否存在該鍵就可以了。加上數組鍵和值不同的組織索引方式,效率比想象的還高那就非??梢岳斫饬恕?
附代碼
復制代碼 代碼如下:
<?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獲得網站訪問統(tǒng)計信息類Compete API用法實例
這篇文章主要介紹了php獲得網站訪問統(tǒng)計信息類Compete API用法,實例分析了php使用curl獲取Compete統(tǒng)計網站信息的技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-04-04
PHP imagecreatefrombmp 從BMP文件或URL新建一圖像
大家都知道php GD庫可方便的從URL新建一圖像, GD中有imagecreatefromjpeg(),imagecreatefromPNG()....等2012-07-07
php中header設置常見文件類型的content-type
這篇文章主要介紹了php中header設置常見文件類型的content-type的相關資料,需要的朋友可以參考下2015-06-06
phpmyadmin中配置文件現在需要絕密的短語密碼的解決方法
phpmyadmin中配置文件現在需要絕密的短語密碼的解決方法...2007-02-02

