游乐游手机版
首页/编程语言/文章详情

如何检查值是否不在数组中并生成对应的非工作日列表

时间:2026-05-06 08:28
如何检查值是否不在数组中并生成对应的非工作日列表 本文介绍在 PHP 中高效判断当前日期是否未出现在分组工作日数组中,并据此构建非工作日列表的完整实现方法,涵盖 array_column 与 in_array 的正确组合用法、避免重复逻辑、日期格式对齐及结构化输出。 在考勤或排班系统的开发中,我们常

如何检查值是否不在数组中并生成对应的非工作日列表

本文介绍在 PHP 中高效判断当前日期是否未出现在分组工作日数组中,并据此构建非工作日列表的完整实现方法,涵盖 array_column 与 in_array 的正确组合用法、避免重复逻辑、日期格式对齐及结构化输出。

如何检查值是否不在数组中并生成对应的非工作日列表

在考勤或排班系统的开发中,我们常常会遇到一个经典场景:需要根据预设的「工作日规则」,动态判断今天是不是某个组的「非工作日」。具体来说,给定一个包含 `group_id` 和 `day`(其中1代表周日,2代表周一,以此类推至7代表周六)的对象数组 `$work_day_arr`,目标是要找出所有没有将今天设置为工作日的分组,并生成一个结构清晰的 `$day_off` 列表,其格式类似于 `['attendance_group_id' => 'xxx', 'off_date' => 'Y-m-d']`。

听起来很直接,对吧?但实际操作时,一些常见的实现陷阱会让结果偏离预期。先来看看原代码中暴露的三个关键问题:

  1. 逻辑错误:代码中间出现了 `if($work_day->day != $day_now + 1)`,这里的 `$work_day` 变量并未定义(本意应是 `$work_hour`)。更麻烦的是,PHP 的 `date('N')` 返回的是 1(周一)到 7(周日),而业务数据里 `day=1` 表示的是周日,两者语义完全对不上。
  2. 重复写入:原逻辑针对每一条不匹配的工作日记录,都会向结果数组追加一条记录。这直接导致同一个 `group_id` 在结果中重复出现多次,数据冗余严重。
  3. 检测粒度错误:问题的核心在于,判断依据应该是「每个 `group_id` 维度下,其工作日集合是否完全不含今天」,而不是逐条记录进行比对。这个根本性的差异决定了整个算法的设计方向。

那么,正确的解决思路是什么?其实可以归纳为一个清晰的步骤:先按 `group_id` 分组,再提取各组的工作日数字集合,最后检查当前的星期几是否不在该集合中。这里,`array_column()` 配合 `in_array()` 将成为我们的核心工具。

// 1. 获取今日星期几(PHP date('N'):1=周一, 7=周日)
$todayWeekday = (int) date('N');
// 注意:数据中 day=1 表示周日 → 需统一映射!

// 2. 修正日期映射:将 date('N') 转为「1=周日」标准(即:周日→1,周一→2...周六→7)
$normalizedToday = $todayWeekday === 1 ? 7 : $todayWeekday - 1; // 1→7, 2→1, 3→2...7→6

// 3. 按 group_id 分组工作日数据
$groupedWorkDays = [];
foreach ($work_day_arr as $item) {
    $groupId = $item->group_id;
    if (!isset($groupedWorkDays[$groupId])) {
        $groupedWorkDays[$groupId] = [];
    }
    $groupedWorkDays[$groupId][] = (int) $item->day;
}

// 4. 遍历每个分组,检查 normalizedToday 是否不在其工作日列表中
$day_off = [];
$date_now = date('Y-m-d'); // 确保日期格式统一
foreach ($groupedWorkDays as $groupId => $workDays) {
    // 使用 in_array 检查当前标准化星期几是否缺失
    if (!in_array($normalizedToday, $workDays, true)) {
        $day_off[] = (object) [
            'attendance_group_id' => $groupId,
            'off_date' => $date_now
        ];
    }
}

实现代码如上,但有几个关键注意事项必须牢记,它们直接关系到程序的正确性与健壮性:

  • 日期映射必须统一:这是最容易出错的一环。`date('N')` 以周一为1,而业务数据以周日为1。因此,必须进行转换(`$normalizedToday = $todayWeekday === 1 ? 7 : $todayWeekday - 1`),确保比较是在同一套标准下进行。
  • 避免重复:有人可能会想直接用 `array_column($work_day_arr, 'day', 'group_id')` 来分组,但这个方法会覆盖同一 `group_id` 的多条记录,无法满足我们收集所有工作日需求。手动分组是更稳妥的选择。
  • 严格类型比较:在使用 `in_array()` 时,务必启用严格模式(第三个参数设为 `true`),即 `in_array($val, $arr, true)`。这可以防止因 `1 == '1'` 这类隐式类型转换而导致的误判。
  • 性能提示:如果初始数据量非常大,可以考虑在分组后对每个 `$workDays` 数组使用 `array_unique()` 去重,再用 `array_values()` 重置索引。这在某些极端场景下能带来一定的性能优化。

遵循以上方法和注意事项,最终生成的 `$day_off` 列表将为每一个「未安排今日工作」的分组,产出唯一一条记录。整个输出结构清晰,毫无冗余,完全满足生产环境对代码健壮性和数据准确性的要求。

来源:https://www.php.cn/faq/2319682.html
上一篇如何搭建Python项目自动化打包流程_配置Setuptools与PyProject 下一篇Python如何解决多线程下的死锁问题_使用RLock与超时机制优化
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
CentOS与Golang打包常见兼容性问题探讨
编程语言 · 2026-07-01

CentOS与Golang打包常见兼容性问题探讨

CentOS与Golang打包的兼容性问题集中在glibc版本不匹配、交叉编译环境变量错误、依赖库缺失及Go依赖管理不规范。可通过Docker容器编译、选择兼容Go版本、正确设置GOOS GOARCH环境变量、安装对应开发包及使用GoModules解决。

CentOS中Fortran与Python如何协同工作从入门到实战完整教程
编程语言 · 2026-07-01

CentOS中Fortran与Python如何协同工作从入门到实战完整教程

在CentOS中,Fortran与Python可通过f2py、SWIG、共享库调用或subprocess协同。f2py封装Fortran为Python模块,支持数组运算;共享库需手动对齐数据类型;系统调用适合独立计算。

CentOS中Golang打包优化方法
编程语言 · 2026-07-01

CentOS中Golang打包优化方法

在CentOS中优化Golang编译打包,可显著提升编译速度并减小二进制文件体积。关键技巧包括:设置环境变量、使用Go模块管理依赖、编译时添加-ldflags= "-s-w "去除调试信息、利用UPX工具压缩、运行strip清理符号表,以及优化cgo内C代码的编译选项。综合运用这些方法能有效优化最终程序。

在CentOS系统中cpustat与其他工具协同使用的完整方法
编程语言 · 2026-07-01

在CentOS系统中cpustat与其他工具协同使用的完整方法

cpustat作为sysstat包的CPU监控工具,可通过管道与grep等命令配合过滤数据,利用脚本自动记录带时间戳的日志,或结合图形工具查看,也可格式化输出后接入Zabbix、Grafana等Web监控系统,实现可视化与告警。

CentOS中readdir与其他Linux发行版的差异
编程语言 · 2026-07-01

CentOS中readdir与其他Linux发行版的差异

CentOS基于RHEL,与Ubuntu、Debian、Fedora在包管理器(yum dnfvsapt)、默认文件系统(XFSvsext4)等存在差异,但readdir等系统调用遵循POSIX标准,行为一致。