深思 PHP 數(shù)組遍歷的差異(array_diff 的實(shí)現(xiàn))
更新時(shí)間:2008年03月23日 17:46:36 作者:
還是部門無(wú)聊的考題,不過(guò)這次考的是 PHP 的能力。題目如下:
給你兩個(gè)分別有 5000 個(gè)元素的數(shù)組,計(jì)算他們的差集
-- 說(shuō)白了也就是用 PHP 和你認(rèn)為最好的算法實(shí)現(xiàn) array_diff 的算法。初次接到這個(gè)題目,我發(fā)現(xiàn)這非常的簡(jiǎn)單,于是按照以往的經(jīng)驗(yàn)“隨便”寫(xiě)了一個(gè):
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;
}雖然實(shí)現(xiàn)是可以的,但是發(fā)現(xiàn)這個(gè)函數(shù)的效率是慘不忍睹。于是我又重新考慮了下,并優(yōu)化了算法,第二個(gè)函數(shù)看起來(lái)是這個(gè)樣子的:
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 函數(shù)的速度媲美了。但是還有沒(méi)有更優(yōu)化的辦法呢?由 ChinaUnix 上的一篇文章(不好意思,作弊了),我發(fā)現(xiàn) PHP 竟然可以這樣寫(xiě):
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;
}這個(gè)函數(shù)的效率非常的驚人,甚至比原 array_diff 函數(shù)的速度都要快。究其原因,我找到了解釋:
因?yàn)殒I是進(jìn)行 HASH 組織的,查找很快;
而 Value 只是由 Key 組織存放,本身沒(méi)有索引,每次查找都是遍歷??偨Y(jié)
這雖然是 PHP 語(yǔ)言的一個(gè)小竅門,但在遍歷和對(duì)比數(shù)組的值上,如果需要對(duì)比值將其與鍵反轉(zhuǎn)的確比通常的值對(duì)值的比較效率要高得多。
比如,上面的函數(shù)二需要調(diào)用 in_array 函數(shù)需要循環(huán)判斷是否在函數(shù)內(nèi);而函數(shù)三則僅僅判斷這個(gè)數(shù)組是否存在該鍵就可以了。加上數(shù)組鍵和值不同的組織索引方式,效率比想象的還高那就非??梢岳斫饬恕?
附代碼
<?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 "函數(shù) array_diff 運(yùn)行" . (microtime_float() - $time_start) . " 秒\n";
$time_start = microtime_float();
array_diff2($ary_1, $ary_2);
echo "函數(shù) array_diff2 運(yùn)行" . (microtime_float() - $time_start) . " 秒\n";
$time_start = microtime_float();
array_diff3($ary_1, $ary_2);
echo "函數(shù) array_diff3 運(yùn)行" . (microtime_float() - $time_start) . " 秒\n";
$time_start = microtime_float();
array_diff4($ary_1, $ary_2);
echo "函數(shù) array_diff4 運(yùn)行" . (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;
}雖然實(shí)現(xiàn)是可以的,但是發(fā)現(xiàn)這個(gè)函數(shù)的效率是慘不忍睹。于是我又重新考慮了下,并優(yōu)化了算法,第二個(gè)函數(shù)看起來(lái)是這個(gè)樣子的:
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 函數(shù)的速度媲美了。但是還有沒(méi)有更優(yōu)化的辦法呢?由 ChinaUnix 上的一篇文章(不好意思,作弊了),我發(fā)現(xiàn) PHP 竟然可以這樣寫(xiě):
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;
}這個(gè)函數(shù)的效率非常的驚人,甚至比原 array_diff 函數(shù)的速度都要快。究其原因,我找到了解釋:
因?yàn)殒I是進(jìn)行 HASH 組織的,查找很快;
而 Value 只是由 Key 組織存放,本身沒(méi)有索引,每次查找都是遍歷??偨Y(jié)
這雖然是 PHP 語(yǔ)言的一個(gè)小竅門,但在遍歷和對(duì)比數(shù)組的值上,如果需要對(duì)比值將其與鍵反轉(zhuǎn)的確比通常的值對(duì)值的比較效率要高得多。
比如,上面的函數(shù)二需要調(diào)用 in_array 函數(shù)需要循環(huán)判斷是否在函數(shù)內(nèi);而函數(shù)三則僅僅判斷這個(gè)數(shù)組是否存在該鍵就可以了。加上數(shù)組鍵和值不同的組織索引方式,效率比想象的還高那就非??梢岳斫饬恕?
附代碼
復(fù)制代碼 代碼如下:
<?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 "函數(shù) array_diff 運(yùn)行" . (microtime_float() - $time_start) . " 秒\n";
$time_start = microtime_float();
array_diff2($ary_1, $ary_2);
echo "函數(shù) array_diff2 運(yùn)行" . (microtime_float() - $time_start) . " 秒\n";
$time_start = microtime_float();
array_diff3($ary_1, $ary_2);
echo "函數(shù) array_diff3 運(yùn)行" . (microtime_float() - $time_start) . " 秒\n";
$time_start = microtime_float();
array_diff4($ary_1, $ary_2);
echo "函數(shù) array_diff4 運(yùn)行" . (microtime_float() - $time_start) . " 秒\n";
?>
您可能感興趣的文章:
- php中使用key,value,current,next和prev函數(shù)遍歷數(shù)組的方法
- PHP數(shù)組遍歷知識(shí)匯總(包含遍歷方法、數(shù)組指針操作函數(shù)、數(shù)組遍歷測(cè)速)
- PHP遍歷數(shù)組的方法匯總
- PHP 數(shù)組遍歷方法大全(foreach,list,each)
- PHP循環(huán)遍歷數(shù)組的3種方法list()、each()和while總結(jié)
- PHP中使用foreach()遍歷二維數(shù)組的簡(jiǎn)單實(shí)例
- PHP遍歷二維數(shù)組的代碼
- PHP遍歷數(shù)組的三種方法及效率對(duì)比分析
- php數(shù)組聲明、遍歷、數(shù)組全局變量使用小結(jié)
- PHP中使用數(shù)組指針函數(shù)操作數(shù)組示例
- php數(shù)組指針操作詳解
- PHP 數(shù)組操作詳解【遍歷、指針、函數(shù)等】
相關(guān)文章
深入研究PHP中的preg_replace和代碼執(zhí)行
這篇文章主要給大家介紹了關(guān)于PHP中preg_replace和代碼執(zhí)行的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-08-08PHP編程實(shí)現(xiàn)的TCP服務(wù)端和客戶端功能示例
這篇文章主要介紹了PHP編程實(shí)現(xiàn)的TCP服務(wù)端和客戶端功能,結(jié)合實(shí)例形式分析了php基于socket實(shí)現(xiàn)TCP服務(wù)器端與客戶端通信功能的相關(guān)配置、定義與使用技巧,需要的朋友可以參考下2018-04-04php中經(jīng)典方法實(shí)現(xiàn)判斷多維數(shù)組是否為空
傳統(tǒng)的判斷數(shù)組為空 一般用count或者key 而且多維數(shù)組的話很麻煩2011-10-10了解Joomla 這款來(lái)自國(guó)外的php網(wǎng)站管理系統(tǒng)
joomla在國(guó)外很熱,就連臺(tái)灣都有不少站使用joomla,國(guó)內(nèi)就對(duì)joomla缺乏了解。大多都使用dedecms或者phpcms等。在這四個(gè)月來(lái)一直在學(xué)習(xí)joomla,覺(jué)得用它來(lái)建站很方便。2010-03-03php源代碼安裝常見(jiàn)錯(cuò)誤與解決辦法分享
這篇文章主要介紹了在linux服務(wù)器中通過(guò)源代碼安裝php過(guò)程中,經(jīng)常會(huì)遇到的一些問(wèn)題做個(gè)小結(jié),特分享給需要的朋友2013-05-05