
本文介绍如何将多个含学生成绩的二维数组(如不同考试批次)按 student_id 合并为一个去重后的统一数组,并支持字段覆盖或累加逻辑。
在 PHP 开发中,常需将来自不同考试、不同学期或不同科目的学生成绩数据(结构相同但内容互补)合并为单一结构化数组。核心需求是:以 student_id 为唯一标识,合并所有数组;相同 student_id 的记录不重复添加,而是进行字段级合并(如保留 stname、叠加 totals、更新 remarks)。
然而,原始答案中的代码存在明显错误(如 $old_array['student_id'] 应为 $value['student_id']),且未说明合并策略(覆盖 or 累加)、未处理字段冲突、也未最终转为索引数字数组。以下提供健壮、可扩展、生产可用的解决方案。
✅ 正确实现:按 student_id 合并 + 字段智能合并
'1190101', 'stname' => 'Student 1', 'remarks' => '', 'totals' => 21],
['student_id' => '1190102', 'stname' => 'Student 2', 'remarks' => '1', 'totals' => 6],
['student_id' => '1190103', 'stname' => 'Student 3', 'remarks' => '', 'totals' => 11],
['student_id' => '1190104', 'stname' => 'Student 4', 'remarks' => '1', 'totals' => 6],
// ... 其余略
];
$array2 = [
['student_id' => '1190104', 'stname' => 'Student 4', 'remarks' => '', 'totals' => 5],
['student_id' => '1190105', 'stname' => 'Student 5', 'remarks' => '', 'totals' => 5],
];
$array3 = [
['student_id' => '1190106', 'stname' => 'Student 6', 'remarks' => '', 'totals' => 5],
['student_id' => '1190107', 'stname' => 'Student 7', 'remarks' => '', 'totals' => 5],
['student_id' => '1190108', 'stname' => 'Student 8', 'remarks' => '', 'totals' => 5],
];
// ✅ 步骤 1:定义合并策略(关键!)
$mergeStrategy = [
'stname' => 'first', // 学生姓名取首个出现值(通常不变)
'remarks' => 'merge', // remarks 若为空则保留原值;否则用新值覆盖(或拼接)
'totals' => 'sum', // 成绩 totals 累加(如多次考试总分)
];
// ✅ 步骤 2:执行合并(支持任意数量数组)
function mergeStudentsByStudentId(array $arrays, array $strategy = []): array {
$merged = []; // 临时关联数组:key = student_id
foreach ($arrays as $array) {
foreach ($array as $item) {
$id = $item['student_id'] ?? null;
if (!$id) continue; // 跳过无 student_id 的脏数据
// 初始化该学生记录(若首次出现)
if (!isset($merged[$id])) {
$merged[$id] = $item;
continue;
}
// 按策略逐字段合并
foreach ($item as $key => $val) {
if ($key === 'student_id') continue; // ID 不参与合并
$existing = $merged[$id][$key] ?? null;
$method = $strategy[$key] ?? 'first';
switch ($method) {
case 'sum':
$merged[$id][$key] = (int)$existing + (int)$val;
break;
case 'merge':
$merged[$id][$key] = !empty($val) ? $val : $existing;
break;
case 'append':
$merged[$id][$key] = is_array($existing)
? array_merge((array)$existing, [$val])
: [$existing, $val];
break;
default: // 'first' — 保持首次值,跳过后续
break;
}
}
}
}
// ✅ 步骤 3:转为连续数字索引数组(符合问题输出格式)
return array_values($merged);
}
// 执行合并
$result = mergeStudentsByStudentId([$array1, $array2, $array3], $mergeStrategy);
print_r($result);
?>? 输出说明(以 student_id=1190104 为例)
- stname → 保留 'Student 4'(first 策略)
- remarks → 从 '1'(array1)→ 仍为 '1'(array2 的 '' 不覆盖)
- totals → 6 + 5 = 11(sum 策略)
? 注意:问题中示例结果写法 [totals] => 6*[totals] => 5* 是示意性表达,实际应为数值累加(如 11)或结构化存储(如 ['exam1'=>6, 'exam2'=>5])。本方案默认累加,亦可轻松切换为数组形式(启用 'append' 策略)。
⚠️ 关键注意事项
- 数据一致性前提:所有数组必须包含 student_id 字段,且其值全局唯一。
- 类型安全:对 totals 等数值字段使用 (int) 强制转换,避免字符串拼接(如 '6' + '5' → 11 而非 '65')。
- 空值处理:remarks 使用 'merge' 策略,确保非空值优先覆盖空值,符合业务逻辑(如“有评语才更新”)。
- 性能友好:时间复杂度 O(n),适用于数千条记录;如数据量极大(>10万),建议改用数据库 GROUP BY student_id + SUM()。
✅ 总结
合并多维学生成绩数组的核心在于:以 student_id 为键构建关联映射 → 按字段定义合并逻辑 → 最终重索引。本文提供的函数支持灵活策略配置、类型安全、空值智能处理,并可无缝扩展至 N 个数组。开发者只需调整 $mergeStrategy 即可适配不同业务场景(如取最新成绩、保留全部历史、计算平均分等)。











