根据多个列值对数组行进行分组和过滤

Group and filter array rows based on multiple column values

我有一组行,其中包含酒店不同日期的空房情况。我需要过滤数组以确定酒店在哪些日期没有空房。

$array = [
    ["room_id" => "1", "date" => "01-07-2022", "available" => "A"],
    ["room_id" => "2", "date" => "01-07-2022", "available" => "A"],
    ["room_id" => "1", "date" => "02-07-2022", "available" => "A"],
    ["room_id" => "2", "date" => "02-07-2022", "available" => "U"],
    ["room_id" => "1", "date" => "03-07-2022", "available" => "U"],
    ["room_id" => "2", "date" => "03-07-2022", "available" => "U"],
    ["room_id" => "1", "date" => "04-07-2022", "available" => "U"],
]

01-07-2022只有A个条目,所以该日期有空缺。

02-07-2022AU 个条目,因此该日期有空缺。

03-07-2022 只有 U 个条目,因此该日期没有空缺。

04-07-2022只有U,所以那个日期没有空缺。

预期结果表明日期没有空缺::

[
   [
     "room_id" => "2",
     "date" => "03-07-2022"
     "available" => "U"
   ],
   [
     "room_id" => "1",
     "date" => "04-07-2022"
     "available" => "U"
   ],
]

我试过以下方法:

foreach ($roomsArr as $room) {
 if ($room['availability'] === 'U') {
    $unavailable[] = $room;
 }
 else if ($room['availability'] === 'A') {
    $available[] = $room;
 }
}

foreach ($unavailable as $uv) {
    foreach ($available as $av) {
        if ($av['date'] === $uv['date']) {
            if ($av['availability'] === 'A' && $uv['availability'] === 'A') {

            }
            else if ($av['availability'] === 'A' && $uv['availability'] === 'U') {

            }
            else if ($av['availability'] === 'U' && $uv['availability'] === 'U') {
                $arr1[] = $av;
            }

        }
    }
}

我会展示两个 approaches/snippets 具有不同的好处。

首先将它们分成空数组和 non-vacant 数组,然后将这两个数组中的数据按日期分组,这样每个日期就不会出现重复条目​​。

数据分离分组后,只需要比较dates/keys没有空缺的日期和有空缺的日期即可。剩下的就是酒店没有空房的日期。

这可能更容易概念化,但性能不如第二个代码段,因为它执行两个单独的迭代技术。

代码:(Demo)

$hasVacancy = [];
$hasNoVacancy = [];
foreach ($array as $row) {
    if ($row['available'] === 'A') {
        $hasVacancy[$row['date']] = $row;
    } else {
        $hasNoVacancy[$row['date']] = $row;
    }
}

var_export(
    array_values(array_diff_key($hasNoVacancy, $hasVacancy))
);

输出:

array (
  0 => 
  array (
    'room_id' => '2',
    'date' => '03-07-2022',
    'available' => 'U',
  ),
  1 => 
  array (
    'room_id' => '1',
    'date' => '04-07-2022',
    'available' => 'U',
  ),
)

更高效的是,您需要维护一个查找数组以确保某个日期没有可用房间。如果你能理解其中的逻辑,我推荐这个片段。只需要遍历输入数组一次

代码:(Demo)

$hasVacancy = [];
$result = [];
foreach ($array as $row) {
    if ($row['available'] === 'A') {
        $hasVacancy[$row['date']] = $row; // store available as reference
        unset($result[$row['date']]);  // remove potentially stored unavailable row for date
    } elseif (!isset($hasVacancy[$row['date']])) {
        $result[$row['date']] = $row;  // is unavailable and no availables found
    }
}
var_export(array_values($result));
// same result as previous snippet