array_reduce不递归处理多维数组,需先用array_walk_recursive扁平化再累加;多级键聚合则用复合键分组累计;注意显式初始值、强制类型转换及避免修改原数组。

直接用 array_reduce 处理多维数组会失败
array_reduce 本身不递归,它只遍历数组第一层。如果传入的是多维数组(比如 [1, [2, 3], 4]),回调函数拿到的 $item 可能是子数组,但 array_reduce 不会自动展开它——你得自己判断并处理嵌套结构。
递归累加所有数值:先 flatten 再 reduce
推荐做法是把“递归汇总”拆成两步:先扁平化(提取所有数字),再累加。这样逻辑清晰、类型安全、不易出错。
- 用
array_walk_recursive收集所有标量值(跳过键名和数组/对象) - 过滤掉非数字值(如 null、字符串非数字、布尔值)
- 用
array_reduce对纯数值数组求和
示例代码:
<?php
function sumAllNumbers($data) {
$flattened = [];
array_walk_recursive($data, function($value) use (&$flattened) {
if (is_numeric($value)) {
$flattened[] = (float)$value;
}
});
return array_reduce($flattened, fn($carry, $item) => $carry + $item, 0.0);
}
$mixed = [
'price' => 199.99,
'tax' => ['vat' => 25.5, 'fee' => '3.2'],
'items' => [
['id' => 1, 'cost' => '89.5'],
['id' => 2, 'cost' => 120],
],
'meta' => ['notes' => 'final', 'valid' => true],
];
echo sumAllNumbers($mixed); // 输出:438.19
?>
立即学习“PHP免费学习笔记(深入)”;
按多级键聚合求和(如 user_id + item_id)
这不是“递归”,而是分组后累加。适合销售/库存类数据:同一用户+同一商品的 quantity 合并。
关键点:用复合键做唯一标识,比如 $key = $item['user_id'] . '|' . $item['item_id'],再在 array_reduce 中累计。
示例:
<?php
$source = [
['user_id' => 1, 'item_id' => 101, 'quantity' => 5],
['user_id' => 1, 'item_id' => 102, 'quantity' => 2],
['user_id' => 1, 'item_id' => 101, 'quantity' => 3], // 重复项
['user_id' => 2, 'item_id' => 101, 'quantity' => 7],
];
$grouped = array_reduce($source, function($carry, $item) {
$key = $item['user_id'] . '|' . $item['item_id'];
if (!isset($carry[$key])) {
$carry[$key] = ['user_id' => $item['user_id'], 'item_id' => $item['item_id'], 'quantity' => 0];
}
$carry[$key]['quantity'] += (int)$item['quantity'];
return $carry;
}, []);
// 转回索引数组
$result = array_values($grouped);
print_r($result);
?>
避坑要点:类型、空值与初始值
PHP 8.1 对类型更严格,这些细节直接影响结果是否可靠:
-
必须显式传
$initial:空数组时返回 null,后续加法会触发 warning;建议用0.0或[]明确类型 - 回调里必须 return:漏写 return,$carry 下轮变成 null,计算中断
-
数值字段强制转类型:用
(float)或(int),避免"100" + "20"得到120(隐式转换)或"10020"(拼接) - 不要在 reduce 里改原数组:它不是 foreach,不适合边遍历边 unset 或重排



















