2009-11-13 5 views
10

私は、何時に基づいて配列の値を決定するサイトを作っています。私はこのひどい(機能的な)スクリプトを書いて、もっと簡潔にできるかどうか疑問に思っています。私はcase/switchステートメントから始めましたが、複数の条件付きステートメントを処理するのに問題がありました。ここで汚い行為だ:ちょうど恐ろしいPHP関数を書きましたが、何か助けが必要です(elseif chain-switch?)

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文を持っています。誰かが私がちょうどコーダーのブロックを持っていたことを確認してください、そして、これを行う良い方法があるのですか?

EDIT:それは私が(うまくいけば)

EDIT 2やってるかを理解する方が簡単ですので、私はラフ本当回のUnixタイムスタンプを変更:を現在壊れたJavascriptのクロックを許しますが、これはしてください私が取り組んでいるサイト:

Time Table

各配列は自分の位置に基づいており、現在の位置に基づいて15個あります。それは開始時間と終了時間がわかっている小さな問題のドメインなので、柔軟性は重要ではなく、すべてを書いているだけです。時間がどのように連続しているかを見ることができ、一度に1つの文字列だけを選択する必要があります。

あなたはこのような何かやって、switchステートメントを使用することができます
+1

選択したタイムスタンプに数学はありますか? –

+0

数学はあります。 $は分割され、数回丸められます –

+0

いくつの条件がありますか?それらは重複していますか、またはそれぞれの条件は排他的ですか? –

答えて

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 
} 

最後に、全体のインライン部分を置き換えますあなたの1つの関数呼び出しを使用してコード:

$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には「Refactoring」という素晴らしい本があり、コードを一度に1ステップずつクリーンアップし、各ステップでテストしてから最終的にテストする理由を説明しています機能的に同等であることをテストしながら、意味を持たない卸売機能を置き換えます。

+1

それはすべての大きなアドバイスです。冗長ですが、きれいです。私はハックです。ありがとう! –

+2

それに伴う問題は、200以上の州が200以上の機能を持っている場合です(彼はすでに最大13の州です)。状態を増やしてコードを増やすべきではなく、一部の(できれば外部の)データブロックを増やすべきです。 –

+0

$ FLIGHT_START_TIME = 1258956001にすることもできます。 $ FLIGHT_END_TIME = 1260511201;これらの日付/時刻をハードコーディングするのではなく、柔軟性が必要な場合は動的です。 –

2

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

私はこのコードが不快だと思っていますが、downvoteしません。あなたの要素の配列をはっきり読める形式にするのはなぜですか?または2つの別々の配列を使用しますか? – Zak

7

それはやり過ぎかもしれないが、私はすべての時間を置くことができるように、私はこのような何かをやっているだろう1つの明確なスポットの範囲である:

@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がそれを必要としているかどうかは明らかではありませんが、有用ではないコードを想像するのは難しいです。 –

+0

ありがとうございます。リードの答えがちょうど私のように見えるように改造されているように見えるので、あなたはそう考えるしかありません。 :) –

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

コマンドパターンを知りたい場合があります。この状況でも役立ちます。

関連する問題