
本文介绍如何将包含 id 和年份的 php 关联数组,按年份聚合、去重 id 并升序排序,最终生成以年份为键、有序 id 数组为值的分组结构。
本文介绍如何将包含 id 和年份的 php 关联数组,按年份聚合、去重 id 并升序排序,最终生成以年份为键、有序 id 数组为值的分组结构。
在实际开发中(如日志归档、作品年表、用户活动统计等场景),我们常需对多条记录按时间维度(如年份)进行聚合,并确保每个年份下关联的 ID 唯一且有序。给定原始数据:
$arr = [
['id' => 1, 'year' => 1999],
['id' => 1, 'year' => 2022],
['id' => 2, 'year' => 2020],
['id' => 1, 'year' => 2020]
];
目标是得到如下结构:年份为键,对应 ID 列表去重后升序排列(注意:示例中 "2020" : "1", "2" 隐含去重逻辑——虽然 id=1 出现多次,但只保留一次)。
✅ 解决方案:分组 + 去重 + 排序
核心思路分三步:
- 按年份分组:遍历原数组,以 year 为键构建嵌套数组;
- 自动去重:在向年份组追加 ID 前,先检查是否已存在(或使用 array_unique 后处理);
- 统一排序:对每个年份下的 ID 数组调用 sort() 实现升序。
以下是健壮、可复用的函数实现:
function groupByIdAndYear(array $items): array
{
$groupedByYear = [];
foreach ($items as $item) {
$year = (string)$item['year']; // 强制转字符串,避免数字键与字符串键混淆(如 2020 vs '2020')
$id = $item['id'];
// 初始化该年份的 ID 数组(若不存在)
if (!isset($groupedByYear[$year])) {
$groupedByYear[$year] = [];
}
// 仅当 ID 尚未存在时才添加(实现去重)
if (!in_array($id, $groupedByYear[$year], true)) {
$groupedByYear[$year][] = $id;
}
}
// 对每个年份下的 ID 数组升序排序
foreach ($groupedByYear as $year => &$ids) {
sort($ids, SORT_NUMERIC); // 显式指定数值排序,避免字符串比较导致 10 1, 'year' => 1999],
['id' => 1, 'year' => 2022],
['id' => 2, 'year' => 2020],
['id' => 1, 'year' => 2020]
];
$result = groupByIdAndYear($items);
print_r($result);
输出结果:
Array
(
[1999] => Array ( [0] => 1 )
[2020] => Array ( [0] => 1 [1] => 2 )
[2022] => Array ( [0] => 1 )
)
? 关键注意事项:
- in_array(..., true) 启用严格类型检查,防止 0 == '0' 类型误判;
- sort($arr, SORT_NUMERIC) 确保 10 正确排在 2 之后(而非字符串排序的 '10'
- 年份转为字符串键((string)$item['year'])可避免后续 JSON 编码时键被强制转为数字(JSON 对象键必须为字符串);
- 若需输出为 JSON 格式(如 API 响应),直接 json_encode($result, JSON_PRETTY_PRINT) 即可;
- 性能提示:对于超大数据集(>10k 条),可改用 array_flip + array_keys 替代 in_array 提升去重效率。
该方案简洁清晰、无依赖、兼容 PHP 7.4+,适用于绝大多数业务场景。掌握此模式后,你可轻松扩展为按「年-月」分组、添加计数统计或合并其他字段。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











