使用array_reduce处理二维数组必须显式指定初始值,求和用0、拼接用''、构建数组用[],否则首轮$carry为子数组导致错误。

array_reduce 二维数组累加求和的写法
直接用 array_reduce 处理二维数组时,如果不显式初始化累加器(第二个参数),PHP 会把第一个子数组当初始值,后续迭代容易报错或逻辑错乱。关键在于:**必须传入明确的初始值,且类型要和你要的结果一致**。
比如对二维数组每行的 price 字段求和:
$data = [
['id' => 1, 'price' => 100],
['id' => 2, 'price' => 250],
['id' => 3, 'price' => 80],
];
$total = array_reduce($data, function ($carry, $item) {
return $carry + $item['price'];
}, 0); // ← 这个 0 就是必须的初始值
- 漏掉第三个参数
0,$carry第一次就是整个子数组,$carry + $item['price']会变成Array + integer,结果为0或触发 notice - 初始值类型要匹配目标:求和用
0,拼接字符串用'',构建新数组用[] - 如果字段可能不存在,记得加
?? 0防止 notice:$carry + ($item['price'] ?? 0)
用 array_reduce 构建新二维数组(如过滤+重组)
常见需求:从原始二维数组中提取某些字段,组成结构更扁平的新数组。这时初始值必须是数组,且每次返回的都得是数组。
$users = [
['name' => 'Alice', 'age' => 30, 'city' => 'Beijing'],
['name' => 'Bob', 'age' => 25, 'city' => 'Shanghai'],
];
$namesAndCities = array_reduce($users, function ($carry, $user) {
$carry[] = ['name' => $user['name'], 'city' => $user['city']];
return $carry;
}, []); // ← 初始值必须是空数组 []
- 忘记初始化为
[],第一次迭代时$carry是第一个$user数组,$carry[] = ...会往原数组加键,结果不可控 - 不能在闭包里用
array_push($carry, ...)然后不返回 ——array_reduce依赖你 显式 return 当前累加结果 - 如果想去重或跳过某些项,直接在闭包里
if判断,符合条件才$carry[] = ...
嵌套 array_reduce 处理多级结构(如分组统计)
遇到「按 category 分组求 sum」这类需求,单层 array_reduce 不够用,得套一层:外层按 key 聚合,内层对同组数据累加。
立即学习“PHP免费学习笔记(深入)”;
$sales = [
['category' => 'A', 'amount' => 100],
['category' => 'B', 'amount' => 200],
['category' => 'A', 'amount' => 150],
];
$grouped = array_reduce($sales, function ($carry, $sale) {
$cat = $sale['category'];
$carry[$cat] = ($carry[$cat] ?? 0) + $sale['amount'];
return $carry;
}, []);
// 结果:['A' => 250, 'B' => 200]
- 这里初始值
[]是对的,但访问$carry[$cat]前必须用?? 0,否则未定义索引会 warning - 别试图在闭包里用
isset($carry[$cat])再分支赋值 —— 多余,??更简洁安全 - 如果分组值是复杂结构(比如对象或带空格的字符串),注意 key 合法性;必要时用
md5()或urlencode()规范化
为什么不用 foreach?什么时候坚持用 array_reduce?
array_reduce 的价值不在“能不能做到”,而在“是否适合表达意图”。它天然适合无副作用、纯函数式的累积逻辑。
- 当你需要链式调用(比如
array_filter(...) → array_reduce(...)),用array_reduce更连贯 - 团队代码风格统一要求函数式写法,或配合其他高阶函数(如
array_map)时,保持一致性比省几行代码重要 - 但若逻辑含多次 break/continue、异步操作、或需中间调试输出,硬套
array_reduce反而难读难调 —— 此时老实用foreach - 性能上无本质差异,PHP 7.4+ 对两者优化都很到位,别为“看起来更函数式”牺牲可维护性
真正容易被忽略的是:每次调用 array_reduce 前,花两秒想清楚——这个 $carry 初始值到底该是什么类型、会不会在第一轮就被当成数据用。这个问题没想清,后面所有逻辑都是空中楼阁。



















