按日期列的年月值对二维数组的行进行分组,并计算每组中的出现次数

问题描述 投票:0回答:4

所以我有这个代码:

$avaDates = [
    ['date_starts' => '2024-03-01'],
    ['date_starts' => '2024-03-09'],
    ['date_starts' => '2024-04-05'],
    ['date_starts' => '2024-04-09'],
    ['date_starts' => '2024-04-15'],
    ['date_starts' => '2024-05-03']
];
$sum = 0;
$months = '';
foreach ($avaDates as $date) {
    $monthCheck = substr($date['date_starts'], 0, -3);
    if ($months !== $monthCheck) {
        $months = $monthCheck;
        $dateFormat = date("F-Y", strtotime($months));

        echo strtolower($dateFormat) . ' ' . $sum . "\n";

        $sum = 0;
    }
    $sum++;
}

实际输出是这样的:

march-2024 0
april-2024 2
may-2024 3

我正在寻找这个输出:

march-2024 2
april-2024 3
may-2024 1

我似乎无法使逻辑发挥作用。这是运行我的示例的沙箱的链接:https://onlinephp.io/c/47724

php arrays multidimensional-array grouping counting
4个回答
1
投票

你需要进行分组和计数,你可以这样做来得到:

$avaDates = [['date_starts'=>'2024-03-01'],['date_starts'=>'2024-03-09'],['date_starts'=>'2024-04-05'],['date_starts'=>'2024-04-09'],['date_starts'=>'2024-04-15'],['date_starts'=>'2024-05-03']];

$groupDates = array_reduce($avaDates, function ($months, $date) {
    $dateFormat = date("F-Y", strtotime($date['date_starts']));
    if (isset($months[$dateFormat])) {
        $months[$dateFormat]++;
    } else {
        $months[$dateFormat] = 1;
    }
    return $months;
});
print_r($groupDates);

数组reduce函数允许您同时迭代数组和组并返回一个值,在本例中,返回一个包含按月分组及其计数的新数组。

要打印数组,您可以通过以下方式完成:

foreach ($groupDates as $month => $count ) {
 echo $month . '->' . $count . "\n";
}

您可以在这里找到代码:https://onlinephp.io/c/47724


1
投票

我认为如果您修剪日期值,您可以使用

array_count_values
来获取计数。比如:

$avaDates = [['date_starts'=>'2024-03-01'],['date_starts'=>'2024-03-09'],['date_starts'=>'2024-04-05'],['date_starts'=>'2024-04-09'],['date_starts'=>'2024-04-15'],['date_starts'=>'2024-05-03']];
foreach($avaDates as $key => $date){
    $avaDates[$key]['date_starts'] = substr($date['date_starts'], 0, 7);
}
foreach(array_count_values(array_column($avaDates, 'date_starts')) as $date => $count){
    echo date('F-Y', strtotime($date . '-01')) . ' ' . $count . PHP_EOL;
}

应该这样做。甚至可以使用

array_map
来缩短它。


1
投票
  1. 将月份总和 echo 转换为函数 (
    print_month_sum()
    )。
  2. 在第 first 迭代中,将
    $months
    分配给
    $monthCheck
    ,并将
    1
    添加到总和中(如果需要打印)。
  3. 最后迭代中:
    • 始终至少打印一次总和。
    • 如果月份
       没有
      发生变化,请在打印前将 1 添加到总和中。
    • 如果月份did发生变化,则进行额外输出。
function print_month_sum($months, $sum) {
    $dateFormat = date("F-Y", strtotime($months));
    echo strtolower($dateFormat).' '.$sum."\n";
}

$avaDates = [['date_starts'=>'2024-03-01'],['date_starts'=>'2024-03-09'],['date_starts'=>'2024-04-05'],['date_starts'=>'2024-04-09'],['date_starts'=>'2024-04-15'],['date_starts'=>'2024-05-03']];
$sum = 0;
$months = '';
foreach ($avaDates as $i => $date) {
    $is_first = ($i === 0);
    $is_last = ($i === count($avaDates) - 1);
    $monthCheck = substr($date['date_starts'], 0, -3);
    if ($is_first) {
        $months = $monthCheck;
    }
    if($months !== $monthCheck || $is_last){
        $last_changed = ($months !== $monthCheck && $is_last);

        $sum += $is_first || ($is_last && !$last_changed) ? 1 : 0;
        print_month_sum($months, $sum);

        if ($last_changed) {
            print_month_sum($monthCheck, 1);
        }
        $months = $monthCheck;
        $sum = 0;
    }
    $sum ++;
}

但是按照其他答案中的建议使用数组函数会更安全。


1
投票

我会将数据准备和数据呈现分开。 (演示)

$result = [];
foreach ($avaDates as ['date_starts' => $d]) {
    $FY = date("F-Y", strtotime($d));
    $result[$FY] = ($result[$FY] ?? 0) + 1;
}
foreach ($result as $fy => $count) {
    echo strtolower("$fy $count\n");
}

如果保证输入数据已排序,那么您可以在处理各个组时在同一循环内进行打印,但它涉及一些更笨重的脚本。 (演示)

$cached = null;
$count = 0;
foreach($avaDates as ['date_starts' => $d]) {
    $FY = date("F-Y", strtotime($d));
    if ($cached !== $FY) {
        if ($cached !== null) {
            echo " $count\n";
            $count = 0;
        }
        echo strtolower($FY);
    }
    $cached = $FY;
    ++$count;
}
if ($count) {
    echo " $count";
}
© www.soinside.com 2019 - 2024. All rights reserved.