在开发过程中,我们经常会从数据库查询或者接口调用中得到多维数组结构,比如订单下包含多个商品,每个商品又有多个规格的价格数值,这时候就需要把数组中所有层级的数值全部累加起来得到总和。如果只处理数组的第一层,就会遗漏深层嵌套的数值,导致统计结果错误。

什么是多维查询结果数组
多维数组指的是数组的元素本身也是数组,可能存在多层嵌套的情况,比如下面这种常见的查询结果结构:
$queryResult = [
'order_id' => 1001,
'total_base' => 200,
'goods' => [
[
'goods_id' => 1,
'price' => 150,
'discount' => 20,
'specs' => [
'weight_fee' => 10,
'pack_fee' => 5
]
],
[
'goods_id' => 2,
'price' => 300,
'discount' => 50,
'specs' => [
'weight_fee' => 15,
'pack_fee' => 8
]
]
],
'extra_fee' => 30
];
这个数组里既有字符串类型的键,也有数值类型的键,数值分布在不同的层级中,我们需要把所有数值都累加得到最终结果。
递归遍历实现累加
递归是最直观的处理多维数组的方式,思路是遍历数组的每个元素,如果元素是数组就继续递归调用自身,如果是数值就累加到总和里。
function sumMultiArrayRecursive($array, &$total = 0) {
foreach ($array as $value) {
if (is_array($value)) {
// 如果是数组,递归处理
sumMultiArrayRecursive($value, $total);
} elseif (is_numeric($value)) {
// 如果是数值,累加到总和
$total += $value;
}
}
return $total;
}
// 调用方法
$sum = 0;
$result = sumMultiArrayRecursive($queryResult, $sum);
echo $result; // 输出 798
这种方法的逻辑清晰,代码容易理解,但是如果数组的嵌套层级非常深,可能会出现递归栈溢出的问题,而且递归调用本身会有一定的性能开销。
迭代栈方式实现累加
为了避免递归的潜在问题,我们可以使用迭代栈的方式来处理,把需要遍历的数组依次压入栈中,循环处理栈里的元素。
function sumMultiArrayIterative($array) {
$total = 0;
$stack = [$array];
while (!empty($stack)) {
$current = array_pop($stack);
foreach ($current as $value) {
if (is_array($value)) {
// 把子数组压入栈中
$stack[] = $value;
} elseif (is_numeric($value)) {
// 累加数值
$total += $value;
}
}
}
return $total;
}
// 调用方法
$result = sumMultiArrayIterative($queryResult);
echo $result; // 输出 798
迭代栈的方式不会受到递归深度的限制,适合处理层级非常深的多维数组,性能也相对更稳定。
使用内置函数组合实现
如果是PHP开发环境,还可以利用array_walk_recursive函数结合自定义回调来实现,这个函数会自动递归遍历数组的所有叶子节点。
function sumMultiArrayByBuiltin($array) {
$total = 0;
array_walk_recursive($array, function($value) use (&$total) {
if (is_numeric($value)) {
$total += $value;
}
});
return $total;
}
// 调用方法
$result = sumMultiArrayByBuiltin($queryResult);
echo $result; // 输出 798
这种方式代码更简洁,不需要自己写递归或者栈的逻辑,但是array_walk_recursive函数内部也是基于递归实现的,所以深度嵌套时同样有递归栈的问题。
不同方法的适用场景
我们可以根据实际场景选择合适的方法:
- 如果数组层级不多,追求代码可读性,优先选择递归遍历或者内置函数组合的方式
- 如果数组层级很深,或者不确定嵌套深度,优先选择迭代栈的方式避免栈溢出
- 如果还需要同时处理非数值的字段,迭代栈的方式更容易扩展逻辑
注意事项
在处理多维数组累加的时候,要注意几个问题:
1. 确认数组中的数值类型,避免把字符串类型的数字或者其他类型的值错误累加,可以用is_numeric做判断2. 如果数组中存在对象类型的元素,需要先判断元素类型,避免遍历出错
3. 累加的时候注意变量的作用域,递归方法中如果用局部变量存储总和,需要在递归调用时传递变量引用,否则总和不会生效
按照上面的方法处理,就可以正确累加多维查询结果数组中的所有数值,得到准确的统计结果。