我正在制作一个网站,根据时间确定数组的值。我写了这个糟糕的(功能)脚本,我想知道我是否可以让它更简洁。我开始使用case / 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
语句。有人可以确认我刚刚编写了编码器块并且有更好的方法吗?
编辑:我将Unix时间戳更改为粗略的实际时间,因此更容易理解我在做什么(希望如此)
编辑2:请原谅当前损坏的Javascript时钟,但这是我正在处理的网站:
每个阵列都基于我的位置,并且根据它的时间有15个“它们当前”。这是一个具有已知开始/结束时间的小问题域,因此灵活性不是关键,只需将其全部写入。您可以看到时间是如何连续的,并且一次只需要选择一个字符串数组。
答案 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
}
最后,用单个函数调用替换代码的整个内联部分:
$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 :(得分: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,但我想它类似。
答案 2 :(得分: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;
此方法只能在时间没有间隙(一个接一个的范围)时使用。
希望这有帮助。
答案 3 :(得分:2)
您可以使用switch语句,执行以下操作:
switch (true)
{
case $now < 1258783201:
// your stuff
break;
case $now < 1258783201
// more of your stuff
break;
//...
}
至少有点干净......
答案 4 :(得分: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];
您还需要考虑是否需要“&lt;”或“&lt; =”condition。
答案 5 :(得分:0)
您可能想学习命令模式;它也可以在这种情况下提供帮助。