Php 显示天数序列

Php 显示天数序列,php,date,days,Php,Date,Days,假设我有这些数字数组,它们对应于一周中的几天(从周一开始): 如何有效地将这些数组转换为C样式注释中所示的所需字符串?任何帮助都将不胜感激。以下代码应该可以工作: <?php // Create a function which will take the array as its argument function describe_days($arr){ $days = array("Monday", "Tuesday", "Wednesday", "Thursday", "Frida

假设我有这些数字数组,它们对应于一周中的几天(从周一开始):


如何有效地将这些数组转换为C样式注释中所示的所需字符串?任何帮助都将不胜感激。

以下代码应该可以工作:

<?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
?>

我尝试并测试了以下内容:

/* 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);
/*周一至周日*/
$days1=数组(1,2,3,4,5,6,7);
/*星期一至星期三及星期日*/
$days2=数组(1,2,3,7);
/*星期三和星期日*/
$days3=数组(3,7);
/*周一至周三和周五至周日*/
$days4=数组(1,2,3,5,6,7);
/*周一至周三、周五和周日*/
$days5=数组(1,2,3,5,7);
/*星期一、星期三、星期五和星期日*/
$days6=数组(1,3,5,7);
函数displayDays($days=array()){
//1:创建时段,并将其分组到具有开始和结束日期的数组中
$periods=array();
$periodIndex=0;
$previousDay=-1;
$nextDay=-1;
foreach($placeInList=>$currentDay的天数){
//如果前一天和第二天(在$days列表中)存在,请获取它们。
如果($placeInList>0){
$previousDay=$days[$placeInList-1];
}
如果($placeInList$period的期间){
如果($key>0){
//不是第一节课
如果($key”;
}
显示天数($天1);
显示天数($days2);
显示天数($天3);
显示天数($days4);
显示天数($days5);
显示天数($days6);

返回星期几。在这个函数中,0是星期一,6是星期天,这就是为什么我每次使用“-1”:你的星期一是1,星期天是7。

我们可以将数组问题转化为字符串问题,并使用正则表达式(regex)解决方案。。。它间接地检查所有条件和案例

PS:当我们有短数组和少量案例时,这种算法构造是安全的,并提供完整的解决方案

哦,是的,我们还可以将周数翻译成其他语言(参见$lang参数)

多语言和正则表达式解决方案 测试:

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)
测试电话:

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"

他们会一直井然有序吗?是的。如果没有,它们可以被分类。有趣的问题,但如果你能提供你的问题尝试,它是在PHP标签赞赏(可能在网站上的其他地方也一样)+3对于一个没有尝试的问题来说,这个问题出人意料地高——这些问题有时会吸引反对票,正如你所知道的
:)
@Félix,这当然是一个有趣的挑战。尽管如此,IMO的所有海报都应该首先意识到提供代码的想法——如果只是为了“陷入困境”,让自己成为一名更好的程序员。我认为,这里有一个共识,那就是自己动手比给出一个高质量的答案更有教育意义。@halfer:同意,我应该试着自己解决这个问题,也许可以问我如何改进代码。我想我还是要试试看,因为我想在编码方面做得更好。你的例子没有给出“星期一-星期三和星期五”,而是给出了“星期一-星期五”。我喜欢你的解决方案,看起来比我的“痛苦”要少。但是你能评论一下吗?我不是什么都懂。(我目前正在查看它以了解所做的工作,但如果已经有一些信息,则会更容易。:)它不适用于1,3,5,7。它给出的结果是:星期一、星期三、星期五和星期天,应该是星期一、星期三、星期五和星期天。2、4、6的结果相同。它给出的是星期二、星期四和星期六,而不是星期二、星期四和星期六。我必须静静地阅读它,以了解您的代码在做什么。与我不同的是将事物形象化的方式!你说的比我的优雅。它在执行时间/服务器资源方面是否也更高效?问题是,我觉得我的答案更容易理解——当然对我来说——我不想说我觉得我的更好(一点也不!),事实上我想知道你的答案是否更好以及为什么。好的,多语言的。当你说安全的时候,我的不是?若有,原因为何?真正的问题是,我想了解并提高我的PHP技能,我不是在这里说“我的代码很好”。)@仙人掌,对不起,我编辑了,现在你可以测试了。就像一个解析器。。。您的算法还可以(!),这只是一个奇特的算法,用于说明“正则表达式解决方案”。也许表现最差(你能做一个基准测试吗?),是的,“可以理解”:只有在“序列中断”和“两天或两天以上”的情况下表现更好(见评论)。感谢所有这些解释!我对正则表达式不是很熟悉(只有当我需要正则表达式时,我才会使用它,例如,当我必须检查电子邮件地址时),所以这个sol
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)
/* 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"