Как разделить время дня на 3 ведра: утром, днем ​​и вечером? - PullRequest
0 голосов
/ 02 ноября 2018

Я хочу посчитать значения из массива, который содержит определенное число. По сути, я хочу построить график посещений и хочу сделать это как «утро», «день» и «вечер». Поэтому я хочу посчитать время, например, 17:38 как 17, а затем подсчитать их, чтобы я мог классифицировать, были ли посещения утром, днем ​​или вечером.

$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

Ответы [ 7 ]

0 голосов
/ 02 ноября 2018

Используя 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) } 
*/
0 голосов
/ 03 ноября 2018

Это первый раз, когда я использовал «оператор космического корабля» или «оператор трехстороннего сравнения» в фрагменте, который не вызывал usort().

Он идеально подходит для этой задачи, потому что вы хотите сгенерировать три сегмента для ваших значений времени.

Оператор космического корабля возвращает одно из трех различных значений: -1, 0 и 1. Его задача состоит в том, чтобы сравнить две строки и решить, является ли значение слева less than, equal to или greater than значением правой стороны - тогда оно возвращает соответствующее числовое значение, упомянутое в моем предыдущем предложении.

Чтобы настроить этот уникальный оператор сравнения (доступный с php7 +), нам нужно свести входные числа так, чтобы они могли быть правильно «объединены».

Большинство людей спешат на explode() (и слишком часто не используют 3-й параметр (limit), чтобы сообщить php, что требуется не более 2 элементов). Я этого не делаю, потому что мне не нравится генерировать массив из строки только для захвата подстроки. Поскольку значения времени предсказуемо отформатированы, лучшим инструментом для этой задачи будет substr($time, 0, 2), но за ним следует strstr($time, ':', true), а если вы хотите быть хитрым "$time[0]$time[1]".

Надеюсь, мои встроенные комментарии прояснят любые другие недоразумения по поводу моего сжатого и мощного фрагмента. (Всего 4 строки рабочего кода!)

Код: ( Демо )

$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";
}

Разбивка по значениям времени 0 до 23:

//  |--------------------------------------------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]
0 голосов
/ 02 ноября 2018

Это должно быть сделано в несколько строк:

$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]);

Демо здесь

0 голосов
/ 02 ноября 2018

Здесь приходит другое решение

<?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;
}
0 голосов
/ 02 ноября 2018

ДЕЙСТВИТЕЛЬНО упрощенно, вы можете сделать это в выражении 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>";
0 голосов
/ 02 ноября 2018

Вы можете сделать это, создав переменные счетчика. Затем мы можем создать диапазоны временных интервалов, используя range(). Затем получите значения перед : в строке времени как часы, а затем сравните их с диапазоном, если он находится в диапазоне, добавьте 1 к счетчику.

<code><?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) .'
'; echo '
'. print_r($afternoonCount,1) .'
'; echo '
'. print_r($eveCount,1) .'
';

рефов:

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

0 голосов
/ 02 ноября 2018

Самый простой вариант:

$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 вместо строк.

...