PHP实现:按连续日期与相同MinStay值分组日期二维数组
合并连续日期且MinStay值相同的条目
我有2023-11-01至2024-01-04的日期数据,部分日期对应不同的MinStay值。现有输入数组:
$input = [ ['date' => '2023-11-01', 'MinStay' => 1], ['date' => '2023-11-02', 'MinStay' => 1], ['date' => '2023-11-03', 'MinStay' => 1], ['date' => '2023-11-04', 'MinStay' => 2], ['date' => '2023-11-05', 'MinStay' => 2], ['date' => '2023-11-06', 'MinStay' => 2], ['date' => '2023-12-10', 'MinStay' => 1], ['date' => '2023-12-11', 'MinStay' => 1], ['date' => '2023-12-12', 'MinStay' => 3], ['date' => '2023-12-13', 'MinStay' => 2], ['date' => '2023-12-14', 'MinStay' => 2], ['date' => '2024-01-01', 'MinStay' => 4], ['date' => '2024-01-02', 'MinStay' => 4], ['date' => '2024-01-03', 'MinStay' => 4], ['date' => '2024-01-04', 'MinStay' => 4], ];
期望将连续日期且MinStay相同的条目合并为日期范围,得到如下输出:
$output = [ ['dateFrom' => '2023-11-01', 'dateTo' => '2023-11-03', 'MinStay' => 1], ['dateFrom' => '2023-11-04', 'dateTo' => '2023-11-06', 'MinStay' => 2], ['dateFrom' => '2023-12-10', 'dateTo' => '2023-12-11', 'MinStay' => 1], ['dateFrom' => '2023-12-12', 'dateTo' => '2023-12-12', 'MinStay' => 3], ['dateFrom' => '2023-12-13', 'dateTo' => '2023-12-14', 'MinStay' => 2], ['dateFrom' => '2024-01-01', 'dateTo' => '2024-01-04', 'MinStay' => 4], ];
我尝试了以下代码,但未达到预期效果:
$arr = []; foreach ($input as $date) { if ($date['MinStay'] == 1) { $arr[] = [ 'dateFrom' => $date['date'], 'dateTo' => $date['date'], 'MinStay' => $date['MinStay'], ]; } }
解决方案
核心思路是遍历过程中跟踪当前合并的分组,判断当前条目是否和当前分组满足「MinStay相同且日期连续」的条件,满足则更新分组结束日期,否则存入当前分组并创建新分组。
完整实现代码:
$input = [ ['date' => '2023-11-01', 'MinStay' => 1], ['date' => '2023-11-02', 'MinStay' => 1], ['date' => '2023-11-03', 'MinStay' => 1], ['date' => '2023-11-04', 'MinStay' => 2], ['date' => '2023-11-05', 'MinStay' => 2], ['date' => '2023-11-06', 'MinStay' => 2], ['date' => '2023-12-10', 'MinStay' => 1], ['date' => '2023-12-11', 'MinStay' => 1], ['date' => '2023-12-12', 'MinStay' => 3], ['date' => '2023-12-13', 'MinStay' => 2], ['date' => '2023-12-14', 'MinStay' => 2], ['date' => '2024-01-01', 'MinStay' => 4], ['date' => '2024-01-02', 'MinStay' => 4], ['date' => '2024-01-03', 'MinStay' => 4], ['date' => '2024-01-04', 'MinStay' => 4], ]; $output = []; $currentGroup = null; foreach ($input as $item) { $currentDate = new DateTime($item['date']); if ($currentGroup === null) { $currentGroup = [ 'dateFrom' => $item['date'], 'dateTo' => $item['date'], 'MinStay' => $item['MinStay'] ]; continue; } $groupEndDate = new DateTime($currentGroup['dateTo']); $nextDay = (clone $groupEndDate)->modify('+1 day'); // 判断是否属于同一分组:MinStay相同且日期是上一日期的次日 if ($item['MinStay'] === $currentGroup['MinStay'] && $currentDate == $nextDay) { $currentGroup['dateTo'] = $item['date']; } else { $output[] = $currentGroup; $currentGroup = [ 'dateFrom' => $item['date'], 'dateTo' => $item['date'], 'MinStay' => $item['MinStay'] ]; } } // 加入最后一个分组 if ($currentGroup !== null) { $output[] = $currentGroup; } // 验证结果 print_r($output);
代码关键点
- 使用
DateTime对象处理日期,避免手动解析字符串的误差,准确判断日期连续性 - 通过
currentGroup变量动态维护当前合并的分组,无需提前分组 - 遍历结束后必须将最后一个未存入的分组加入结果数组
内容的提问来源于stack exchange,提问作者Hola
相关产品推荐
相关产品推荐

