【问题标题】:How to separate times of day into 3 buckets: morning, afternoon, and evening?如何将一天中的时间分成 3 个时段:早上、下午和晚上?
【发布时间】:2018-11-02 14:31:51
【问题描述】:

我正在寻找包含特定数字的数组中的值。基本上,我希望绘制一个图形访问,并希望将其作为“早上”、“下午”和“晚上”进行。所以我想计算时间,例如 17:3817,然后计算它们,这样我就可以分类访问是早上、下午还是晚上。

$time_array = array("17:45","13:12","09:29","17:32","16:49","14:18");

$counts = array_count_values($time_array);
$morning_counts = $counts['09'] + $counts['10'] + $counts['11'];
$afternoon_counts = $counts['12'] + $counts['13'] + $counts['14'] + $counts['15'] + $counts['16'];
$evening_counts = $counts['17'] + $counts['18'] + $counts['19'] + $counts['20'] + $counts['21'] + $counts['22'] + $counts['23'];

样本数据的预期输出:

$morning_counts = 1
$afternoon_count = 3
$evening_counts = 2

【问题讨论】:

    标签: php arrays time grouping bucket


    【解决方案1】:

    您可以通过创建计数器变量来做到这一点。然后我们可以使用range() 创建时间范围范围。然后获取时间字符串中:之前的值作为小时,然后将其与范围进行比较,如果在范围内,则将计数器加1。

    <?php
        $time_array = array("17:45","13:12","09:29","17:32","16:49","14:18");
    
        # create counter vars
        $mornCount = 0;
        $afternoonCount = 0;
        $eveCount = 0;
    
        # create range of times to compare against
        $mornRange = range(0, 11);
        $afternoonRange = range(12, 16);
        $eveRange = range(17, 23);
    
        foreach ($time_array as $time)
        {
            $compareTimeArr = explode(':', $time); # get first two chars of time
            $compareTime = $compareTimeArr[0];
    
            if (in_array($compareTime, $mornRange)) {
                $mornCount++;
            } elseif (in_array($compareTime, $afternoonRange)) {
                $afternoonCount++;
            } elseif (in_array($compareTime, $eveRange)) {
                $eveCount++;
            }
        }
    
        echo '<pre>'. print_r($mornCount,1) .'</pre>';
        echo '<pre>'. print_r($afternoonCount,1) .'</pre>';
        echo '<pre>'. print_r($eveCount,1) .'</pre>';
    

    参考:

    https://secure.php.net/manual/en/function.in-array.php

    https://secure.php.net/manual/en/function.explode.php

    https://secure.php.net/manual/en/function.range.php

    【讨论】:

      【解决方案2】:

      最简单的选择:

      $time_array = array("17:45","13:12","09:29","17:32","16:49","14:18");
      $times = [];
      foreach ($time_array as $time) {
          $times[] = substr($time, 0, 2);
      }
      
      // Proceed with original code, but swap $time_array for $times
      

      我觉得它很丑。我通常建议使用 DateTimes 或 DatePeriods 而不是字符串。

      【讨论】:

      • 好的,我是从数据库中得到这个的,所以也许只是 COUNT where date BETWEEN function and do it 3 次?
      • 您的代码似乎对我不起作用,它返回的总次数远高于现有代码的总次数?
      【解决方案3】:

      如果你真的很简单,你可以在 switch 语句中做到这一点

      <?php
      $time_array = array("17:45","13:12","09:29","17:32","16:49","14:18");
      
      $morn = 0;
      $after = 0;
      $eve = 0;
      $other = 0;
      foreach ($time_array as $time) {
          $t = explode(':',$time)[0];
          switch ($t) {
              case '09':
              case '10':
              case '11':
              case '12':
                  $morn++;
                  break;
      
              case '13':
              case '14':
              case '15':
              case '16':
                  $after++;
                  break;
      
              case '17':
              case '18':
              case '19':
              case '20':
              case '21':
              case '22':
              case '23':
                  $eve++;
                  break;
              default:
                  $other++;
          }
      }
      echo "Morning = $morn<br>";
      echo "Afternoon = $after<br>";
      echo "Evening= $eve<br>";
      echo "Other = $other<br>";
      

      【讨论】:

        【解决方案4】:

        这应该只需要几行代码:

        $counts = array_reduce($time_array, function($counts, $time) {
          $hour = (int)substr($time, 0, 2);
          $moment = in_array($hour, range(9, 12)) ? 'morning' : (in_array($hour, range(13, 16)) ? 'afternoon' : 'evening');
          $counts[$moment]++;
          return $counts;
        }, ['morning' => 0, 'afternoon' => 0, 'evening' => 0]);
        

        Demo here

        【讨论】:

        • 这没有在任何地方引用 $time_array 变量?
        • @Nathan $time_array 是传递给函数的数组——我不希望看到它再次出现在这个 sn-p 中。
        【解决方案5】:

        这里有另一个解决方案

        <?php
        $time_array = array("17:45","13:12","09:29","17:32","16:49","14:18");
        $counts = countValues($time_array);
        $morning_counts = $counts['09'] + $counts['10'] + $counts['11'] + $counts['12'];
        $afternoon_counts = $counts['12'] + $counts['13'] + $counts['14'] + $counts['15'] + $counts['16'];
        $evening_counts = $counts['17'] + $counts['18'] + $counts['19'] + $counts['20'] + $counts['21'] + $counts['22'] + $counts['23'] + $counts['24'];
        
        var_dump($morning_counts, $afternoon_counts, $evening_counts);
        
        function countValues($time_array) {
            $result = [];
            for ($i = 0; $i <= 23; $i++) {
                $key = ($i < 10) ? ('0' . $i) : (string) $i;
                $result[$key] = 0;
            }
            foreach ($time_array as $time) {
                $key = strstr($time, ':', true);
                $result[$key]++;
            }
            return $result;
        }
        

        【讨论】:

          【解决方案6】:

          使用preg_match 您还可以获得次数。

          $time_array = array("17:45","13:12","09:29","17:32","16:49","14:18");
          function time_results($time_array){
              $result = array('morning_counts'=>0,'afternoon_counts'=>0,'evening_counts'=>0,'total'=>0);
              $result['total'] = count($time_array);
              foreach($time_array as $time){
                  if(preg_match('/^(09|10|11|12)\:*/',$time)){
                      $result['morning_counts'] += 1;
                  }else if(preg_match('/^(13|14|15|16)\:*/',$time)){
                      $result['afternoon_counts'] += 1;
                  }else if(preg_match('/^(17|18|19|20|21|22|23|24)\:*/',$time)){
                      $result['evening_counts'] += 1;
                  }
              }
              return $result;
          }
          
          var_dump(time_results($time_array));
          /*
          result : array(4) { ["morning_counts"]=> int(1) ["afternoon_counts"]=> int(3) ["evening_counts"]=> int(2) ["total"]=> int(6) } 
          */
          

          【讨论】:

          • 我担心复制粘贴这些正则表达式模式的人。 1.您不需要捕获组2.字符类将减少需要使用的管道条件的数量3.您不需要转义 : 4. :* 对样本数据没有任何逻辑意义。此外,这里可以避免正则表达式,并且可能会证明这个答案在页面上效率最低。
          【解决方案7】:

          这是我第一次在不调用 usort() 的 sn-p 上使用“宇宙飞船运算符”又名“3 路比较运算符”。

          它非常适合这项任务,因为您想为您的时间值生成三个存储桶。

          spaceship 运算符返回三个不同值之一:-101。它的工作是比较两个字符串并确定左侧的值是less thanequal to 还是greater than 右侧的值——然后返回我上一句中提到的相应数值。

          要设置这个唯一的比较运算符(可从 php7+ 获得),我们需要将输入的数字归结为可以正确“分桶”。

          大多数人都急于explode()(并且经常不使用第三个参数(限制)来通知 php 需要不超过 2 个元素)。我不这样做,因为我不喜欢仅仅为了捕获子字符串而从字符串生成数组。因为时间值的格式是可预测的,所以完成任务的最佳工具是substr($time, 0, 2),但紧随其后的是strstr($time, ':', true),如果你想变得棘手,"$time[0]$time[1]"

          我希望我的内联 cmets 能够消除关于我简洁而强大的 sn-p 的任何其他困惑。 (只需 4 行工作代码!)

          代码:(Demo)

          $time_array = ["17:45", "13:12", "09:29", "17:32", "16:49", "14:18"];
          
          $buckets = array_fill_keys([-1, 0, 1], 0);  // initialize buckets with 0 values
          
          foreach ($time_array as $time) {
              ++$buckets[(int)sqrt(substr($time, 0, 2) - 8) <=> 2];
              //                                            ^^^^^-- 3-way comparison versus 2 
              //                                       ^^^--------- subtract 8 from the two-digit number
              //                   ^^^^^^^^^^^^^^^^^^^------------- extract first two digits from time string
              //             ^^^^^^-------------------------------- get squareroot value
              //         ^^^^--------------------------------- convert to integer (truncate decimals)
          }
          
          echo "Morning Count: {$buckets[-1]}\n";   // Hours: 00:00 to 11:59 ->12hrs (calculates as: 0, 1)
          echo "Afternoon Count: {$buckets[0]}\n";  // Hours: 12:00 to 16:59 -> 5hrs (calculates as: 2)
          echo "Evening Count: {$buckets[1]}";      // Hours: 17:00 to 23:59 -> 7hrs (calculates as: 3, 4)
          

          输出:

          Morning Count: 1
          Afternoon Count: 3
          Evening Count: 2
          

          计算过程如何分解?

          foreach (range(0, 23) as $t) {
              $calc = (float)sqrt($t - 8);
              echo "$t: " , (int)$calc , " ... [float value from sqrt was: $calc]\n";
          }
          

          从时间值023 的细分:

          //  |--------------------------------------------input time value
          //  v  v-----------------------------------------final calculated value
          //                                       vvv-----before converted to integer value
              0: 0 ... [float value from sqrt was: NAN]
              1: 0 ... [float value from sqrt was: NAN]
              2: 0 ... [float value from sqrt was: NAN]
              3: 0 ... [float value from sqrt was: NAN]
              4: 0 ... [float value from sqrt was: NAN]
              5: 0 ... [float value from sqrt was: NAN]
              6: 0 ... [float value from sqrt was: NAN]
              7: 0 ... [float value from sqrt was: NAN]
              8: 0 ... [float value from sqrt was: 0]
              9: 1 ... [float value from sqrt was: 1]
              10: 1 ... [float value from sqrt was: 1.4142135623731]
              11: 1 ... [float value from sqrt was: 1.7320508075689]
              12: 2 ... [float value from sqrt was: 2]
              13: 2 ... [float value from sqrt was: 2.2360679774998]
              14: 2 ... [float value from sqrt was: 2.4494897427832]
              15: 2 ... [float value from sqrt was: 2.6457513110646]
              16: 2 ... [float value from sqrt was: 2.8284271247462]
              17: 3 ... [float value from sqrt was: 3]
              18: 3 ... [float value from sqrt was: 3.1622776601684]
              19: 3 ... [float value from sqrt was: 3.3166247903554]
              20: 3 ... [float value from sqrt was: 3.4641016151378]
              21: 3 ... [float value from sqrt was: 3.605551275464]
              22: 3 ... [float value from sqrt was: 3.7416573867739]
              23: 3 ... [float value from sqrt was: 3.8729833462074]
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-08-29
            • 1970-01-01
            • 2018-10-22
            • 2015-02-19
            • 1970-01-01
            • 1970-01-01
            • 2020-01-26
            • 1970-01-01
            相关资源
            最近更新 更多