2009-11-13 31 views
10

我正在製作一個網站,它基於什麼時間確定數組的值。我寫了這個糟糕的(功能性)腳本,想知道我是否可以使它更簡潔。我從一個case/switch語句開始,但很難獲得多個條件。這裏的卑鄙:我剛剛寫了一個可怕的PHP函數,我需要一些幫助(elseif鏈 - 開關?)

if ($now < november 18th) { 
    $array_to_use = $home; 
} 
elseif (november 18th < $now && $now < november 21st) { 
    $array_to_use = $driving; 
} 
elseif (november 21st < $now && $now < november 22nd) { 
    $array_to_use = $flying; 
} 
... 
... 
... 
elseif (february 1st < $now) { 
    $array_to_use = $arrived; 
} 
else { 
    $array_to_use = $default; 
} 

時間表實際上是更復雜,並在其13個elseif語句。有人可以確認我只是有編碼器的阻止,並有更好的方法來做到這一點?

編輯:我改變了Unix的時間戳來粗略實際時間,以便它更容易理解我在做什麼(希望)

編輯2:請原諒當前破碎的Javascript時鐘,但這是我正在處理的網站:

Time Table

每個數組都基於我的位置,並且有15個「他們當前」基於它的時間。這是一個具有已知開始/結束時間的小問題域,因此靈活性並不重要,只需將其全部寫入即可。您可以看到時間是如何連續的,並且一次只需要選擇一個字符串數組。

+1

數學到你選擇的時間戳嗎? – 2009-11-13 19:45:01

+0

有數學,是的。 $現在被劃分並舍入幾次 – 2009-11-13 19:47:31

+0

有多少條件?它們是重疊的,還是每個條件都是獨佔的? – 2009-11-13 19:48:00

回答

13

首先,請請請拿出你的硬編碼的數字,並把它們變成常量。

$FLIGHT_START_TIME = 1258956001; 
$FLIGHT_END_TIME = 1260511201; 

其次,我會做小功能對每個條件句:

function isFlying($time) 
{ 
    return ($FLIGHT_START_TIME < $time && $time < $FLIGHT_END_TIME); 
} 

第三,把你的整套條件句,並把它變成一個功能,讓你的當前狀態,並在你的函數替換調用:

function getStateArrayForTime($time) 
{ 

    if (isDriving($time) 
    { 
     return $driving; 
    } 
    if (isFlying($time)) 
    { 
     return $flying; 
    } 
...etc 
} 

最後,更換整個在線部分代碼使用單一的函數調用:

$currentState = getStateArrayForTime($now); 

正如其他海報也有評論,在這一點上,你可以使用數據表驅動函數返回的狀態,如果你只知道開始和結束時間將狀態參數:

所以更換getStateArrayForTime與執行:「爲什麼在這個順序做的事情」

function getStateArrayForTime ($time) 
{ 
// 
$states = array (
    array("startTime" => 1258956001, "endTime" => 1260511201, "state" => $flying), 
    array("startTime" => 1260511201, "endTime" => 1260517000, "state" => $driving), 
..etc... 
); 
    foreach($states as $checkStateArray) 
    { 
     if($checkStateArray['startTime'] < $time && $time < $checkStateArray['endTime']) 
     { 
      return $checkStateArray['state']; 
     } 
    } 
    return null; 
} 

最後,有些人可能會問除了在應用程序中,我不能聲稱信用,但Martin Fowler有一本名爲「重構」的偉大着作,解釋了爲什麼您一次只執行一個步驟清理代碼,然後在每個步驟進行測試,然後最終取而代之的是批發功能沒有意義的功能,同時測試它們在功能上是否相同。

+1

這是所有偉大的建議。詳盡,但乾淨。我是一個黑客。謝謝! – 2009-11-13 19:54:49

+2

問題在於如果你最終有200個狀態你有200個更多的功能(他已經達到13個)。增加更多的狀態不應該增加代碼,只是一些(最好是外部的)數據塊。 – 2009-11-13 19:55:50

+0

您也可以使$ FLIGHT_START_TIME = 1258956001; $ FLIGHT_END_TIME = 1260511201;如果您還需要這種靈活性,那麼也是動態的,而不是硬編碼這些日期/時間 – 2009-11-13 19:56:54

2

您可以使用switch語句,做這樣的事情:

switch (true) 
{ 
    case $now < 1258783201: 
     // your stuff 
     break; 
    case $now < 1258783201 
     // more of your stuff 
     break; 
    //... 
} 

這是至少有一點清潔劑...

0

事情是這樣的:

$array_to_use = null; 
$dispatch = array(1258783201, $home, 1258956001, $driving, ..., $arrived); 
for ($i=0; i<count($dispatch); $i+=2) { 
    if ($now<$dispatch[$i]) { 
     $array_to_use = $dispatch[$i+1]; 
     break; 
    } 
} 
if ($array_to_use==null) $array_to_use = $dispatch[count($dispatch)-1]; 

您還需要考慮是否需要 「<」 或 「< =」 狀態。

+1

我認爲這段代碼很噁心,但不會倒退。爲什麼不把你的元素組成一個清晰可讀的格式?或使用2個獨立的數組? – Zak 2009-11-13 20:28:10

7

這可能是矯枉過正,但我​​會做這樣的事情,這樣我可以把在一個清晰的斑點所有的時間段:

@timeWindows = ({ start -> 0, end -> 1258783201, array -> $home }, 
       ... , 
       {start -> 1260511201, end -> MAXVAL, array -> $arrived}); 

,然後循環像

$array_to_use = $default; 

foreach (my $window in @timeWindows) { 
    if (($now > $window->start) && ($now < $window->end)) { 
     $array_to_use = $window->array; 
     last; 
    } 
} 

對不起,它在Perl中,我不知道PHP,但我想它是相似的。

+1

這是最好的答案,因爲它允許以編程方式確定時間邊界。目前尚不清楚OP是否需要,但很難想象有用的代碼不會。 – 2009-11-13 19:59:37

+0

謝謝。它看起來像只是修改爲像我的領導的答案,所以我想你不是唯一這樣想的人。 :) – 2009-11-13 21:29:00

3

您可以將時間和數組用於數組,並循環它們以進行選擇。

$Selctions = array(
    1258783201 => $Home, 
    1258956001 => $Driving, 
    1260511201 => $Flying, 
    ... 
    1260511201 => $Arriving 
); 

// MUST SORT so that the checking will not skip 
ksort($Selction); 
$TimeToUse = -1; 
$Now  = ...; 
foreach ($Selctions as $Time => $Array) { 
    if ($Now < $Time) { 
     $TimeToUse = $Time; 
     break; 
    } 
} 
$ArrayToUse = ($TimeToUse != -1) ? $Selctions[$TimeToUse] : $Default;

當次沒有間隙(後右另一個範圍)只能使用此方法。

希望這會有所幫助。

0

您可能想要了解命令模式;它也可以幫助在這種情況下。

相關問題