PHP中end()数组赋值未达预期,合并日期时间数组求助
咱们一个一个来解决你的问题,都是PHP里常见的小坑,别担心~
问题1:PHP中使用end()赋值不符合预期
你肯定是踩了end()函数的一个关键误区——end()返回的是数组最后一个元素的副本,不是引用,所以直接给end()的返回值赋值完全无效,根本不会修改原数组。
举个你可能写错的例子:
$arr = ['a', 'b', 'c']; end($arr) = 'd'; // 这行代码等于白写! print_r($arr); // 输出还是 ['a', 'b', 'c']
给你几种正确的实现方式,按需选择:
- 如果你的PHP版本是7.3及以上,直接用
array_key_last()拿到最后一个键再赋值,最简洁:$arr = ['a', 'b', 'c']; $lastKey = array_key_last($arr); $arr[$lastKey] = 'd'; print_r($arr); // 输出 ['a', 'b', 'd'] - 要兼容低版本PHP的话,先调用end()移动数组指针,再用key()获取最后一个元素的键:
$arr = ['a', 'b', 'c']; end($arr); // 把指针移到最后一个元素 $lastKey = key($arr); // 获取当前指针位置的键 $arr[$lastKey] = 'd'; print_r($arr); // 同样得到 ['a', 'b', 'd'] - 如果是纯索引数组,也可以用
array_pop()+array_push()组合,但这种会改变数组长度,适合只替换最后一个元素的场景:$arr = ['a', 'b', 'c']; array_pop($arr); array_push($arr, 'd');
问题2:合并同一天的时间区间,取最早start和最晚end
你的需求核心是按日期分组聚合,循环处理是可行的,但可以优化得更清晰。这里给你两种实现思路:
方式1:foreach循环(直观易懂,新手友好)
// 你的原始时间数组示例 $timeEntries = [ ['start' => '2018-01-01 12:00', 'end' => '2018-01-01 15:00'], ['start' => '2018-01-01 12:00', 'end' => '2018-01-01 17:00'], ['start' => '2018-01-02 09:00', 'end' => '2018-01-02 11:00'], ]; $result = []; foreach ($timeEntries as $entry) { // 提取日期部分作为分组键(比如'2018-01-01') $date = date('Y-m-d', strtotime($entry['start'])); if (!isset($result[$date])) { // 第一次遇到这个日期,直接初始化 $result[$date] = $entry; } else { // 对比start时间,保留更早的那个 if (strtotime($entry['start']) < strtotime($result[$date]['start'])) { $result[$date]['start'] = $entry['start']; } // 对比end时间,保留更晚的那个 if (strtotime($entry['end']) > strtotime($result[$date]['end'])) { $result[$date]['end'] = $entry['end']; } } } // 如果需要去掉日期键,转成纯索引数组,用array_values() $result = array_values($result); print_r($result);
方式2:array_reduce(简洁的函数式写法)
如果你喜欢函数式编程风格,用array_reduce可以一行完成分组聚合:
$timeEntries = [ ['start' => '2018-01-01 12:00', 'end' => '2018-01-01 15:00'], ['start' => '2018-01-01 12:00', 'end' => '2018-01-01 17:00'], ]; $result = array_values(array_reduce($timeEntries, function($carry, $item) { $date = date('Y-m-d', strtotime($item['start'])); if (!isset($carry[$date])) { $carry[$date] = $item; } else { // 因为你的日期格式是标准的Y-m-d H:i,直接用字符串比较min/max也有效 $carry[$date]['start'] = min($carry[$date]['start'], $item['start']); $carry[$date]['end'] = max($carry[$date]['end'], $item['end']); } return $carry; }, [])); print_r($result);
两种方式最终都会输出你想要的结果:
Array ( [0] => Array ( [start] => 2018-01-01 12:00 [end] => 2018-01-01 17:00 ) )
内容的提问来源于stack exchange,提问作者yoyoma
相关产品推荐
相关产品推荐

