
本文介绍如何在 php 关联数组中,基于 id 分组并快速获取每组中 year 字段最大的最新记录,核心思路是先按年份降序排序,再遍历去重,时间复杂度可控且代码简洁易维护。
本文介绍如何在 php 关联数组中,基于 id 分组并快速获取每组中 year 字段最大的最新记录,核心思路是先按年份降序排序,再遍历去重,时间复杂度可控且代码简洁易维护。
在处理如用户档案、日志记录或版本化数据等场景时,常需从重复 ID 的多条记录中提取“最新一条”(通常以时间字段如 Year 判定)。PHP 原生数组操作即可高效完成该任务,无需依赖数据库或额外扩展。
✅ 推荐方案:排序 + 首次出现即保留(最优实践)
该方法逻辑清晰、性能稳定(O(n log n) 主要来自排序),且天然保持结果可预测性:
-
先对原始数组按
Year降序排序(最新年份排最前); - 遍历排序后数组,用 ID 作为键构建临时缓冲数组;
- 仅当某 ID 首次出现时才存入缓冲区——由于已排序,首次即为最新;
-
最后用
array_values()提取纯索引数组,消除 ID 键干扰。
以下是完整可运行示例:
<?php
$data = [
['Name' => 'Gary', 'ID' => 1, 'Year' => 2016],
['Name' => 'Miller', 'ID' => 2, 'Year' => 2018],
['Name' => 'Spike', 'ID' => 3, 'Year' => 2019],
['Name' => 'Miller', 'ID' => 2, 'Year' => 2020],
['Name' => 'Gary', 'ID' => 1, 'Year' => 2018],
['Name' => 'Miller', 'ID' => 2, 'Year' => 2019],
['Name' => 'Gary', 'ID' => 1, 'Year' => 2017],
['Name' => 'Spike ', 'ID' => 3, 'Year' => 2020], // 注意 Spike 含空格,实际使用建议 trim()
];
// 步骤1:按 Year 降序排序(PHP 7+ 支持 <=> 船舰操作符)
usort($data, fn($a, $b) => $b['Year'] <=> $a['Year']);
// 步骤2:构建 ID → 最新记录映射
$latestByid = [];
foreach ($data as $row) {
$id = $row['ID'];
// 首次遇到该 ID 时保存(即最大 Year)
if (!isset($latestByid[$id])) {
$latestByid[$id] = $row;
}
}
// 步骤3:转为数值索引数组,便于后续遍历或 JSON 输出
$result = array_values($latestByid);
print_r($result);
?>✅ 输出结果与预期完全一致:
立即学习“PHP免费学习笔记(深入)”;
Array
(
[0] => Array ( [Name] => Miller [ID] => 2 [Year] => 2020 )
[1] => Array ( [Name] => Spike [ID] => 3 [Year] => 2020 )
[2] => Array ( [Name] => Gary [ID] => 1 [Year] => 2018 )
)⚠️ 注意事项与进阶建议
-
空格/大小写敏感:示例中
'Spike '含尾部空格,若Name参与业务逻辑(如去重或展示),建议预处理:$row['Name'] = trim($row['Name']); -
多字段排序需求:若存在同年份多记录需进一步按
ID或Name排序,可扩展usort比较函数,例如:usort($data, fn($a, $b) => $b['Year'] <=> $a['Year'] ?: $a['ID'] <=> $b['ID'] ); -
内存优化提示:对超大数据集(>10 万行),可考虑流式处理或数据库
GROUP BY id HAVING year = MAX(year)替代; -
健壮性增强:生产环境建议添加字段校验(如
isset($row['ID'], $row['Year']))及类型断言(如is_int($row['Year']))。
该方法兼顾可读性、性能与可维护性,是 PHP 数组分组取极值的经典范式,推荐作为标准工具函数封装复用。



















