Search code examples
phparraysgroupingdate-rangecontiguous

Group 2d array of dates and values by contiguous dates with the same value


I have a date range 2023-11-01 to 2024-01-04 and some date have different MinStay value.

This is my array of date range

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

And I want to

$output = [
  [ 'dateForm' => '2023-11-01', 'dateTo' => '2023-11-03', 'MinStay' => 1 ],
  [ 'dateForm' => '2023-11-04', 'dateTo' => '2023-11-06', 'MinStay' => 2 ],
  [ 'dateForm' => '2023-12-10', 'dateTo' => '2023-12-11', 'MinStay' => 1 ],
  [ 'dateForm' => '2023-12-12', 'dateTo' => '2023-12-12', 'MinStay' => 3 ],
  [ 'dateForm' => '2023-12-13', 'dateTo' => '2023-12-14', 'MinStay' => 2 ],
  [ 'dateForm' => '2024-01-01', 'dateTo' => '2024-01-04', 'MinStay' => 4 ],
];

How can I solve this issue.

I'm try using this array but it's not happening.

$arr = [];
foreach ($input as $date) {
    if ($date['MinStay'] == 1) {
        $arr[] = [
            'dateFrom' => $date['date'],
            'dateTo' => $date['date'],
            'MinStay' => $date['MinStay'],
        ];
    }
}

Solution

  • Firstly, loop through the array, keep track of the current date range, and compare the MinStay value with the previous one

    If they are the same, extend the range, otherwise, push the current range to the output and start a new one.

    $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 = [];
    $currentRange = null; // Will store the current range of dates
    
    foreach ($input as $date) {
        // If currentRange is empty, start a new range
        if ($currentRange === null) {
            $currentRange = [
                'dateForm' => $date['date'],
                'dateTo' => $date['date'],
                'MinStay' => $date['MinStay'],
            ];
        } else {
            // Check if MinStay matches the current range's MinStay
            if ($date['MinStay'] === $currentRange['MinStay']) {
                // Extend the date range
                $currentRange['dateTo'] = $date['date'];
            } else {
                // If MinStay changes, push the current range to the output
                $output[] = $currentRange;
    
                // Start a new range
                $currentRange = [
                    'dateForm' => $date['date'],
                    'dateTo' => $date['date'],
                    'MinStay' => $date['MinStay'],
                ];
            }
        }
    }
    
    // Add the last range to the output
    if ($currentRange !== null) {
        $output[] = $currentRange;
    }
    
    // Output the result
    print_r($output);