我们说这些数字数组对应于一周中的天数(从星期一开始):
/* Monday - Sunday */
array(1, 2, 3, 4, 5, 6, 7)
/* Wednesday */
array(3)
/* Monday - Wednesday and Sunday */
array(1, 2, 3, 7)
/* Monday - Wednesday, Friday and Sunday */
array(1, 2, 3, 5, 7)
/* Monday - Wednesday and Friday - Sunday */
array(1, 2, 3, 5, 6, 7)
/* Wednesday and Sunday */
array(3, 7)
如何有效地将这些数组转换为所需的字符串,如C风格的注释所示?任何帮助将不胜感激。
答案 0 :(得分:4)
以下代码应该有效:
<?php
// Create a function which will take the array as its argument
function describe_days($arr){
$days = array("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday");
// Begin with a blank string and keep adding data to it
$str = "";
// Loop through the values of the array but the keys will be important as well
foreach($arr as $key => $val){
// If it’s the first element of the array or ...
// an element which is not exactly 1 greater than its previous element ...
if($key == 0 || $val != $arr[$key-1]+1){
$str .= $days[$val-1]."-";
}
// If it’s the last element of the array or ...
// an element which is not exactly 1 less than its next element ...
if($key == sizeof($arr)-1){
$str .= $days[$val-1];
}
else if($arr[$key+1] != $val+1){
$str .= $days[$val-1]." and ";
}
}
// Correct instances of repetition, if any
$str = preg_replace("/([A-Z][a-z]+)-\\1/", "\\1", $str);
// Replace all the "and"s with commas, except for the last one
$str = preg_replace("/ and/", ",", $str, substr_count($str, " and")-1);
return $str;
}
var_dump(describe_days(array(4, 5, 6))); // Thursday-Saturday
var_dump(describe_days(array(2, 3, 4, 7))); // Tuesday-Thursday and Sunday
var_dump(describe_days(array(3, 6))); // Wednesday and Saturday
var_dump(describe_days(array(1, 3, 5, 6))); // Monday, Wednesday and Friday-Saturday
?>
答案 1 :(得分:3)
/* Monday - Sunday */
$days1 = [1, 2, 3, 4, 5, 6, 7];
/* Monday - Wednesday and Sunday */
$days2 = [1, 2, 3, 7];
/* Wednesday and Sunday */
$days3 = [3, 7];
/* Monday - Wednesday and Friday - Sunday */
$days4 = [1, 2, 3, 5, 6, 7];
/* Monday - Wednesday, Friday and Sunday */
$days5 = [1, 2, 3, 5, 7];
/* Monday, Wednesday, Friday and Sunday */
$days6 = [1, 3, 5, 7];
// creates logic groups out of flat array
function splitIntoSequences(array $days)
{
$collection = [];
do {
$seq = extractSequence($days);
$collection[] = $seq;
$days = array_diff($days, $seq);
}
while (!empty($days));
return $collection;
}
// filters the next sequence
function extractSequence(array $days)
{
sort($days);
$seq = [];
foreach ($days as $day) {
// seq break
if (!empty($seq) && $day - 1 != $seq[count($seq) - 1]) {
return $seq;
}
$seq[] = $day;
}
return $seq;
}
// removes all unneeded steps from sequences
function cleanupSequences(array $collection)
{
$cleanedCollection = [];
foreach ($collection AS $seq) {
if (count($seq) == 1) {
$cleaned = [array_pop($seq)];
} else {
$cleaned = [array_shift($seq), array_pop($seq)];
}
$cleanedCollection[] = $cleaned;
}
return $cleanedCollection;
}
// convert whole collection to daynames
function convertToDaynames(array $collection)
{
$daynameCollection = [];
foreach ($collection AS $seq) {
$days = [];
foreach ($seq as $day) {
$days[] = numberToDay($day);
}
$daynameCollection[] = $days;
}
return $daynameCollection;
}
// number to dayname
function numberToDay($weekday)
{
$relative = sprintf('next Sunday + %d day', $weekday);
$date = new \DateTime($relative);
return $date->format('l');
}
// format output
function format(array $collection)
{
$t = [];
foreach ($collection as $seq) {
$t[] = implode(' - ', $seq);
}
if (count($t) == 1) {
return array_pop($t);
}
$last = array_pop($t);
return sprintf('%s and %s', implode(', ', $t), $last);
}
测试电话:
function makeMeHappy(array $seq)
{
$splitted = splitIntoSequences($seq);
$cleaned = cleanupSequences($splitted);
$daynames = convertToDaynames($cleaned);
return format($daynames);
}
var_dump(makeMeHappy($days1));
// string(15) "Monday - Sunday"
var_dump(makeMeHappy($days2));
// string(29) "Monday - Wednesday and Sunday"
var_dump(makeMeHappy($days3));
// string(20) "Wednesday and Sunday"
var_dump(makeMeHappy($days4));
// string(38) "Monday - Wednesday and Friday - Sunday"
var_dump(makeMeHappy($days5));
// string(37) "Monday - Wednesday, Friday and Sunday"
var_dump(makeMeHappy($days6));
// string(36) "Monday, Wednesday, Friday and Sunday"
答案 2 :(得分:2)
我试过并测试了这个:
/* Monday - Sunday */
$days1 = array(1, 2, 3, 4, 5, 6, 7);
/* Monday - Wednesday and Sunday */
$days2 = array(1, 2, 3, 7);
/* Wednesday and Sunday */
$days3 = array(3, 7);
/* Monday - Wednesday and Friday - Sunday */
$days4 = array(1, 2, 3, 5, 6, 7);
/* Monday - Wednesday, Friday and Sunday */
$days5 = array(1, 2, 3, 5, 7);
/* Monday, Wednesday, Friday and Sunday */
$days6 = array(1, 3, 5, 7);
function displayDays($days = array()) {
// 1: Create periods and group them in arrays with starting and ending days
$periods = array();
$periodIndex = 0;
$previousDay = -1;
$nextDay = -1;
foreach($days as $placeInList => $currentDay) {
// If previous day and next day (in $days list) exist, get them.
if ($placeInList > 0) {
$previousDay = $days[$placeInList-1];
}
if ($placeInList < sizeof($days)-1) {
$nextDay = $days[$placeInList+1];
}
if ($currentDay-1 != $previousDay) {
// Doesn't follow directly (in week) previous day seen (in our list) = starting a new period
$periodIndex++;
$periods[$periodIndex] = array($currentDay);
} elseif ($currentDay+1 != $nextDay) {
// Follows directly previous day, and isn't followed directly (in week) by next day (in our list) = ending the period
$periods[$periodIndex][] = $currentDay;
$periodIndex++;
}
}
$periods = array_values($periods);
// Arrived here, your days are grouped differently in bidimentional array.
// print_r($periods); // If you want to see the new array's structure
// 2: Display periods as we want.
$text = '';
foreach($periods as $key => $period) {
if ($key > 0) {
// Not first period
if ($key < sizeof($periods)-1) {
// Not last period either
$text .= ', ';
} else {
// Last period
$text .= ' and ';
}
}
if (!empty($period[1])) {
// Period has starting and ending days
$text .= jddayofweek($period[0]-1, 1).' - '.jddayofweek($period[1]-1, 1);
} else {
// Period consists in only one day
$text .= jddayofweek($period[0]-1, 1);
}
}
echo $text.'<br />';
}
displayDays($days1);
displayDays($days2);
displayDays($days3);
displayDays($days4);
displayDays($days5);
displayDays($days6);
jddayofweek()
返回星期几。在那个函数中,0是星期一,6是星期日,这就是&#34; -1&#34;每次我都使用它:你的星期一是1,星期日是7。
答案 3 :(得分:2)
我们可以将数组问题转换为字符串问题,并使用正则表达式(正则表达式)解决方案......间接地通过finite automata检查所有条件和案例。
PS:当我们有短阵列和少数情况时,这种算法结构是安全的,并提供完整的解决方案。
哦是的,我们也可以将周数翻译成另一种语言(参见$ lang参数)!
function weekNumbers_toStr($days, $lang='en') {
$and = array('pt'=>'e', 'en'=>'and');
$strWeek = array( // config with more langs!
'pt'=>array("Segunda", "Terça", "Quarta", "Quinta", "Sexta",
"Sábado", "Domingo"),
'en'=> array("Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday", "Sunday")
);
$days = array_unique($days);
sort($days);
$seq = preg_replace_callback( // Split sequence by ",":
'/0246|024|025|026|135|146|246|02|03|04|05|06|13|14|15|16|24|25|26|35|36|46/',
function ($m) { return join( ',' , str_split($m[0]) ); },
join('',$days)
);
// split two or more days by "-":
$seq = preg_replace('/(\d)\d*(\d)/', '$1-$2', $seq);
$a = explode(',',$seq);
$last = array_pop($a);
$n = count($a);
// Formating and translating:
$seq = $n? join(", ",$a): $last;
if ($last && $n) $seq = "$seq $and[$lang] $last";
return preg_replace_callback(
'/\d/',
function ($m) use (&$strWeek,$lang) {
return $strWeek[$lang][$m[0]];
},
$seq
);
} // func
测试:
print "\n".weekNumbers_toStr(array(6,1,2,3,6),'en'); // corrects order and dups
print "\n".weekNumbers_toStr(array(0,1,2,3,6)); // Monday-Thursday and Sunday
print "\n".weekNumbers_toStr(array(3,4,6),'pt'); // Quinta-Sexta e Domingo
print "\n".weekNumbers_toStr(array(3,4,6)); // Thursday-Friday and Sunday
print "\n".weekNumbers_toStr(array(2,3,4,6)); // Wednesday-Friday and Sunday
print "\n".weekNumbers_toStr(array(3,5)); // Thursday and Saturday
print "\n".weekNumbers_toStr(array(0,2,4,6)); // Monday, Wednesday, Friday and Sunday
print "\n".weekNumbers_toStr(array(0)); // Monday
print "\n".weekNumbers_toStr(array()); // (nothing)