
本文介绍在 laravel 或原生 php 中,将含重复设备标识的消费记录数组转换为“设备+起始时间+结束时间+数值”的结构化数组,重点解决字段重命名(timestamp → start/end)与逻辑配对问题。
本文介绍在 laravel 或原生 php 中,将含重复设备标识的消费记录数组转换为“设备+起始时间+结束时间+数值”的结构化数组,重点解决字段重命名(timestamp → start/end)与逻辑配对问题。
在实际开发中(尤其是处理 IoT 设备上报、日志聚合或时间区间统计场景),我们常遇到类似 $consumos 的扁平化时间序列数据:多个相同 device 的记录仅通过 timestamp 区分先后,但业务需要将其两两配对为 start/end 时间段。PHP 本身不提供开箱即用的“字段重命名+分组配对”函数,需结合数组遍历与状态管理实现。
以下提供两种主流方案,均基于原始数据结构,无需额外依赖,兼容 Laravel 和纯 PHP 环境:
✅ 方案一:单次遍历 + 映射暂存(推荐用于任意数量配对)
适用于每个 device 可能有 2、4、6… 偶数条记录,且需严格按出现顺序配对(第一条为 start,第二条为 end,第三条为下一个 start,依此类推):
$map = [];
$return = [];
foreach ($consumos as $item) {
$key = $item['device']; // 以 device 为分组键(也可扩展为 "$item['device']_$item['value']")
if (isset($map[$key])) {
// 已存在该设备的待配对项 → 当前 timestamp 作为 end
$map[$key]['end'] = $item['timestamp'];
$return[] = $map[$key]; // 完成配对,加入结果
unset($map[$key]); // 清空缓存,准备下一对
} else {
// 首次出现 → 初始化为 start
$map[$key] = [
'device' => $item['device'],
'start' => $item['timestamp'],
'value' => $item['value'],
];
}
}
// 注意:若原始数据中某 device 条目数为奇数,最后一个 start 将滞留在 $map 中(无对应 end)
// 如需兜底处理,可在此后追加:foreach ($map as $orphan) { $orphan['end'] = $orphan['start']; $return[] = $orphan; }
⚠️ 方案二:两次遍历 + 批量合并(适合固定两两配对且需保留所有组)
若明确每组仅含两条记录(如严格的一采一报),且希望保留所有设备组(即使未配对完全),可用此方式:
$groups = [];
foreach ($consumos as $item) {
$key = $item['device'];
$groups[$key][] = $item;
}
$return = [];
foreach ($groups as $device => $items) {
// 每两个连续元素组成一组(索引 0→start, 1→end, 2→start, 3→end...)
for ($i = 0; $i $device,
'start' => $items[$i]['timestamp'],
'end' => $items[$i + 1]['timestamp'],
'value' => $items[$i]['value'], // 假设同 device 同 value,否则需自定义逻辑
];
}
// 可选:处理落单项($i 为最后一项且无配对)
}
}
? 关键注意事项
-
分组键选择:示例使用
'device',若需按device + value联合分组,请改为$key = $item['device'] . '_' . $item['value']; -
时间顺序假设:上述代码默认数组输入顺序即业务逻辑顺序(如先上报再确认)。若原始数据时间无序,务必先调用
usort()按timestamp排序:usort($consumos, function($a, $b) { return strtotime($a['timestamp']) strtotime($b['timestamp']); }); -
Laravel 优化提示:在 Eloquent 查询中,可直接使用
groupBy()+min()/max()聚合函数替代 PHP 层处理,例如:Consumption::query() ->select('device', 'value', DB::raw('MIN(timestamp) as start'), DB::raw('MAX(timestamp) as end')) ->groupBy('device', 'value') ->get();
最终输出 $return 即为符合预期的结构化数组,可直接用于 API 返回、视图渲染或后续计算。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











