
本文介绍如何根据预定义的最近7个月时间序列,自动向患者发药记录的 dispatch 数组中插入缺失月份的占位项(quantity: 0),并确保最终数组按时间顺序(由 period 字符串升序)正确排序。
本文介绍如何根据预定义的最近7个月时间序列,自动向患者发药记录的 `dispatch` 数组中插入缺失月份的占位项(`quantity: 0`),并确保最终数组按时间顺序(由 `period` 字符串升序)正确排序。
在医疗或药品分发系统中,常需将离散的发药记录(如每月实际发药量)对齐到连续的时间维度(例如“最近7个月”),以便进行可视化、统计或报表生成。当原始数据中存在月份空缺时(如示例中缺少 2022-5),直接渲染图表可能导致错位或逻辑错误。因此,必须以标准月份序列为准,主动补全缺失项,并将新项插入到正确位置。
核心思路
- 以 months 数组为权威时间基准:它已按时间倒序排列(从近到远),包含 month(数字)、year 和标准化 period(如 "2022-5");
- 遍历每个患者记录的 dispatch:对 months 中每一项,检查其 period 是否已在 dispatch 中存在;
- 若不存在,则构造新对象:{ "month": 5, "year": 2022, "quantity": 0, "period": "2022-5" };
- 统一排序:插入后对整个 dispatch 数组按 period 字符串升序重排(即 2021-12, 2022-1, ..., 2022-6),确保时间线连续且有序。
PHP 实现代码(兼容 PHP 7.4+)
// 假设 $data 是原始 JSON 解码后的对象(含 records)
// $monthsData 是 months JSON 解码后的对象
foreach ($monthsData->months as $targetMonth) {
foreach ($data->records as $record) {
// 检查当前 dispatch 中是否已存在该 period
$exists = array_filter($record->dispatch, function($item) use ($targetMonth) {
return $item->period === $targetMonth->period;
});
if (empty($exists)) {
// 构造缺失月份的占位对象
$newDispatchItem = (object)[
'month' => (int)$targetMonth->position,
'year' => $targetMonth->year,
'quantity' => 0,
'period' => $targetMonth->period
];
$record->dispatch[] = $newDispatchItem;
// 按 period 升序重排(字符串比较即可,因格式统一为 YYYY-M)
usort($record->dispatch, function($a, $b) {
return strcmp($a->period, $b->period);
});
}
}
}关键注意事项
- ✅ period 字符串必须严格一致:如 "2022-5" 与 "2022-05" 不等价,确保 months 和 dispatch 中的 period 格式统一(推荐使用 Y-n 格式,避免前导零);
- ✅ usort 使用 strcmp 安全可靠:因 period 形如 "2021-12", "2022-1",字符串字典序与时间序一致("2022-1" < "2022-10"),无需额外解析;
- ⚠️ 避免重复插入:array_filter + empty() 判断可防止同一 period 被多次添加;
- ⚠️ 性能提示:若 records 或 months 规模较大(如百级),建议将 dispatch 的 period 提取为关联数组键($dispatchMap[$item->period] = $item),将查找复杂度从 O(n) 降至 O(1)。
最终效果验证
处理后,dispatch 数组将严格包含 months 中全部7个 period,按时间升序排列,缺失月份的 quantity 统一设为 0,其余字段完整保留。此结构可直接用于前端 ECharts 图表渲染或后端月度汇总计算,确保数据维度对齐、逻辑健壮。


















