按具有相同值的连续日期对日期和值的二维数组进行分组

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

我的日期范围是 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 ],
];

我想要

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

我该如何解决这个问题。

我尝试使用这个数组,但它没有发生。

$arr = [];
foreach ($input as $date) {
    if ($date['MinStay'] == 1) {
        $arr[] = [
            'dateFrom' => $date['date'],
            'dateTo' => $date['date'],
            'MinStay' => $date['MinStay'],
        ];
    }
}
php arrays grouping date-range contiguous
3个回答
0
投票

首先,循环遍历数组,跟踪当前日期范围,并将

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

0
投票

一个巧妙的方法是执行两个循环:

$temp = [];
foreach ($input as $record) {
    if (!isset($temp[$record['MinStay']])) {
        $temp[$record['MinStay']] = [
            'dateFrom' => $record['date'],
            'dateTo' => $record['date']
        ];
    } else if ($temp[$record['MinStay']]['dateFrom'] > $record['date']) {
        $temp[$record['MinStay']]['dateFrom'] = $record['date'];
    } else if ($temp[$record['MinStay']]['dateTo'] < $record['date']) {
        $temp[$record['MinStay']]['dateTo'] = $record['date'];
    }
    $output = [];
    foreach ($temp as $MinStay => $record) {
        $output []= [
            'MinStay' => $MinStay,
            'dateFrom' => $record['dateFrom'],
            'dateTo' => $record['dateTo']
        ];
    }
}

首先,我们创建一个临时数组,其中存储元素,键为 MinStay 的值。每当我们处理一条记录时,我们都会检查其 MinStay 是否在较早的记录中被处理过。如果没有,那么我们创建这样一个记录,其中 dateFrom 和 dateTo 是日期。否则,我们检查 date 是否小于 dateFrom,在这种情况下,我们将 dateFrom 更新为它,或者,如果它大于 dateTo,则将 dateTo 设置为它。

现在我们有了我们想要的所有组,我们只需要将格式转换为您想要的输出,因此我们再做一个循环,将每个元素转换为您想要的格式并将其插入到输出数组中。


0
投票

为了最大程度地优雅,将引用变量推入结果数组并仅更新当前引用。

您的输入数据不足以揭示不考虑连续日期的解决方案。 我已经扩展了示例输入。

$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' => '2023-12-24', 'MinStay' => 2 ],  // <-- added challenge where same minstay is not on contiguous date
  [ 'date' => '2024-01-01', 'MinStay' => 4 ],
  [ 'date' => '2024-01-02', 'MinStay' => 4 ],
  [ 'date' => '2024-01-03', 'MinStay' => 4 ],
  [ 'date' => '2024-01-04', 'MinStay' => 4 ],
];

代码:(演示

$result = [];
$lastMinStay = null;
foreach ($input as ['date' => $d, 'MinStay' => $ms]) {
    if ($ms !== $lastMinStay || $d !== date('Y-m-d', strtotime("{$ref['dateTo']} +1 day"))) {
        unset($ref);
        $ref = ['dateFrom' => $d, 'dateTo' => $d, 'MinStay' => $ms];
        $result[] =& $ref;
        $lastMinStay = $ms;
        continue;
    }
    $ref['dateTo'] = $d;
}
var_export($result);

输出:

array (
  0 => 
  array (
    'dateFrom' => '2023-11-01',
    'dateTo' => '2023-11-03',
    'MinStay' => 1,
  ),
  1 => 
  array (
    'dateFrom' => '2023-11-04',
    'dateTo' => '2023-11-06',
    'MinStay' => 2,
  ),
  2 => 
  array (
    'dateFrom' => '2023-12-10',
    'dateTo' => '2023-12-11',
    'MinStay' => 1,
  ),
  3 => 
  array (
    'dateFrom' => '2023-12-12',
    'dateTo' => '2023-12-12',
    'MinStay' => 3,
  ),
  4 => 
  array (
    'dateFrom' => '2023-12-13',
    'dateTo' => '2023-12-14',
    'MinStay' => 2,
  ),
  5 => 
  array (
    'dateFrom' => '2023-12-24',
    'dateTo' => '2023-12-24',
    'MinStay' => 2,
  ),
  6 => 
  array (
    'dateFrom' => '2024-01-01',
    'dateTo' => '2024-01-04',
    'MinStay' => 4,
  ),
)
© www.soinside.com 2019 - 2024. All rights reserved.