2011-05-16 95 views
1

如果连续3天或更多天彼此跟随,我正在寻找一个函数,可以从一系列星期几开始下降。这是我的测试代码(使用Test::More测试框架)将星期几列表转换为时间间隔

// function is($result, $expected, $message) 
is(drop_days(""), "", 'Empty'); 
is(drop_days("Mo"), "Mo", 'One Day'); 
is(drop_days("Mo,Tu"), "Mo,Tu", 'Two Days'); 
is(drop_days("Mo,Tu,We"), "Mo-We", 'Three Days'); 
is(drop_days("Mo,Tu,We,Th,Fr,Sa,Su"), "Mo-Su", 'Seven Days'); 
is(drop_days("Mo,Tu,Th,Fr"), "Mo,Tu,Th,Fr", 'Four days with gap'); 
is(drop_days("Mo,Tu,We,Fr"), "Mo-We,Fr", '3 consecutive days, one single day'); 
is(drop_days("Mo,Tu,We,Fr,Sa,Su"), "Mo-We,Fr-Su", '2 pairs of 3 consecutive days'); 

回答

4

有时 “愚蠢” 的做法是最聪明的

function drop_days($s) { 
    static $map = array(
     'Mo,Tu,We,Th,Fr,Sa,Su' => 'Mo-Su', 
     'Mo,Tu,We,Th,Fr,Sa' => 'Mo-Sa', 
     'Mo,Tu,We,Th,Fr'  => 'Mo-Fr', 
     'Mo,Tu,We,Th'   => 'Mo-Th', 
     'Mo,Tu,We'    => 'Mo-We', 
     'Tu,We,Th,Fr,Sa,Su' => 'Tu-Su', 
     'Tu,We,Th,Fr,Sa'  => 'Tu-Sa', 
     'Tu,We,Th,Fr'   => 'Tu-Fr', 
     'Tu,We,Th'    => 'Tu-Th', 
     'We,Th,Fr,Sa,Su'  => 'We-Su', 
     'We,Th,Fr,Sa'   => 'We-Sa', 
     'We,Th,Fr'    => 'We-Fr', 
     'Th,Fr,Sa,Su'   => 'Th-Su', 
     'Th,Fr,Sa'    => 'Th-Sa', 
     'Fr,Sa,Su'    => 'Fr-Su', 
    ); 
    return strtr($s, $map); 
} 
+0

我知道有这样可用的方法。有点不安,我无法找到它。 – Galen 2011-05-17 02:17:39

0

实施例与在is()http://codepad.org/ulJnW3Iu。功能可以按任何顺序接受工作日。

<?php 
function drop_days($string, $atleast = 3) { 
    $weekdays = 'Mo,Tu,We,Th,Fr,Sa,Su'; 
    $weekdays = explode(',', $weekdays); 
    $selected = array(); 
    $sequences = array(); 
    foreach ($weekdays as $weekday) 
     $selected[] = (strpos($string,$weekday)!==false); 
    $i = 0; 
    while ($i<count($weekdays)) { 
     if (!$selected[$i]) { 
      $i++; 
      continue; 
     } 
     if ($i+$atleast<=count($weekdays)) { 
      for ($j=$i+1; $j<count($weekdays); $j++) { 
       if ($selected[$j]) { 
        if ($j+1<count($weekdays)) continue; 
        $sequences[] = $weekdays[$i] . '-' . $weekdays[$j]; 
        break 2; 
       } else { 
        if ($j-$i>=$atleast) 
         $sequences[] = $weekdays[$i] . '-' . $weekdays[$j-1]; 
        else 
         for ($k=$i; $k<$j; $k++) $sequences[] = $weekdays[$k]; 
        $i = $j+1; 
        break; 
       } 
      } 
     } else { 
      $sequences[] = $weekdays[$i]; 
      $i++; 
     } 
    } 
    return implode(',', $sequences); 
} 
?> 
1

另一种方法:

function drop_days($str, $days = 'mo,tu,we,th,fr,sa,su') { 
    $days_i_s = array_flip(explode(',', $days)); 
    $days_i_n = explode(',', $days); 
    $day_string = str_replace(array_keys($days_i_s), array_values($days_i_s), strtolower($str)); 
    return str_replace(array_values($days_i_s), array_keys($days_i_s), preg_replace_callback('~(0,1,2,3,4,5,6)|(1,2,3,4,5,6)|(0,1,2,3,4,5)|(1,2,3,4,5)|(2,3,4,5,6)|(0,1,2,3,4)|(0,1,2,3)|(0,1,2)|(3,4,5,6)|(2,3,4,5)|(2,3,4)|(3,4,5)|(1,2,3,4)|(1,2,3)|(2,3,4)|(4,5,6)~', function($m) use($days_i_n){return $days_i_n[$m[0][0]].'-'.$days_i_n[$m[0][strlen($m[0])-1]] ;}, $day_string)); 
} 

echo drop_days("Mo,Tu,We,Fr,Sa,Su");