2011-05-16 2 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

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"); 
Смежные вопросы