2012-11-19 31 views
4

請看看下面的代碼PHP優化極長開關罩聲明

function GetAreaName($AreaCode) 
{ 
    switch ($AreaCode) 
    { 
    case 201: return 'New Jersey'; 
    case 202: return 'Washington'; 
    // this goes on till 
    case 999: return ''; 
    } 
} 

比方說,如果AREACODE是998那就要經過這麼多的情況下! 我們如何優化這個功能? (沒有使用數據庫。)

我想建立一個數組並在其二進制搜索?但是這意味着每次調用該函數時都會重建數組?我們如何構建數組一次,緩存並在每次調用這個函數時重用?

+0

看起來太長時間 –

回答

7

爲什麼不直接使用的哈希表?

class Area { 

private $areaCodes = array(
      201 => 'New Jersey', 
      202 => 'Washington', 
      // this goes on till 
      999 => ''; 
     ); 

    function getStateByAreaCode ($areaCode) { 

     if (array_key_exists($areaCode, $this->areaCodes)) { 
      return $this->areaCodes[$areaCode]; 
     } else { 
      return false; 
     } 

    } 
} 

這樣稱呼它:

$area = new Area(); 
$city = $area->getStateByAreaCode(303); 

只需保存你的類文件,包括它當你需要它。

您被問及如何防止陣列被創建每個請求: 通過把這個在類中,你至少保持清潔。它在技術上仍然會創建每個請求,但除非您的陣列非常龐大(比美國的區域代碼更大),否則不會帶來性能問題。如果您擔心每次請求時都要構建數組,請查看代碼優化器(如APC或Zend Optimizer)。這基本上是PHP在運行時生成的字節碼並對其進行緩存。

+0

你如何實現這個功能?特別是,您如何避免在每次通話時重建陣列? – erisco

+0

@erisco我已經填寫了代碼,因此它在類的內部工作,並給出了關於使用PHP代碼加速器進行優化的一些提示。如果你不想在每個調用中構建一個數組,那麼你可以將它存儲在數據庫表中。但是,我認爲與構建數組相比,連接到數據庫的時間與請求的時間差異可以忽略不計。 –

3

聽起來像你應該只是將它存儲在您的數據庫。

但是,如果你不能做到這一點,無論是抽象成某種類型的配置文件並將其保存在某種持久的對象,或只使用一個靜態變量:

function foo($key) { 
    static $cache = array(1 => 'abc', 2 => 'def', 3 => 'ghi'); 
    if (array_key_exists($key, $cache)) { 
     return $cache[$key]; 
    } else { 
     //Somehow signal an error (throw an exception, return boolean false, or something) 
    } 
} 

在上面,$cache只會存在一次。 (如果你知道的值永遠不會null,你可以使用isset代替array_key_exists

這是不是很靈活,雖然由於更改數據需要您編輯的代碼。你通常希望你的數據和你的代碼解耦。

這可能意味着將它存儲在某種文件(json,xml,php,無論)中,並將其加載到某種只能創建一次的結構中。然後,您會將該對象或數組傳遞到需要的地方。 (或者,如果你想成爲哈克,你可以使用一個靜態類,我建議針對這雖然。)

+0

看來靜態$緩存仍然會構建每個PHP頁面請求。我環顧四周,發現這 http://stackoverflow.com/a/6062224/1809157 我可能需要將其存儲在用戶會話,至少它是每個用戶只有一次構建。我認爲它仍然不是最好的,它只在我的web應用程序的整個生命週期中構建一次。 – user1809157

+0

@ user1809157除非你使用像'apc',沒有辦法請求之間仍然存在它不接觸某種外源(會話從文件中恢復;數據庫需要的連接; Memcached和家庭需要的連接;等等)。我發佈的'foo'可能會比在會話中存儲更好的性能。 – Corbin

+0

嗯..好吧,我現在只是堅持你的解決方案。謝謝! – user1809157

2

交換條件只有一次評估:

在switch語句,評估條件只有一次,並將結果與​​每個病例語句進行比較。在elseif語句中,將再次評估條件。如果你的情況比簡單的比較更復雜和/或處於緊密的循環中,開關可能會更快。 ➫➫➫

沒有需要優化。然而,閱讀:
In PHP what's faster, big Switch statement, or Array key lookup

如果你想建立一個配置文件,您可以考慮這樣的:

$areas = array 
(
    1 => 'abc', 
    2 => 'def', 
    .. 
); 

然後簡單比較:

if (!isset($areas[$some_code])) 
{ 
    // do something 
} 
else 
{ 
    // ok 
} 
+2

這是問題:「結果與每個病例對照」進行比較。 – erisco

+0

哈哈,先閱讀答案的細節,親愛的選民! – ajreal

+0

@ajreal,[使用'array_key_exists'](http://stackoverflow.com/a/3210982/632951),而不是'isset'。 – Pacerier

0

試試下面的僞代碼

$areas = array('201' => 'New Jersey', 
        '202' => 'Washington', 
        ...... 
        ........ 
        '999' => ''); 
function GetAreaName($AreaCode) 
{ 


    if(isset($areas[$AreaCode])) { 
     return $areas[$AreaCode]; 
    } else { 
     // do something 
    } 

} 
+2

這會在每次調用時重建陣列,問題要避開。 – erisco