
本文详解如何将含 ac_no 和 amount 的二维数组按账户号分组,并为每组内每个元素生成“从当前项到末尾所有金额绝对值之和”的累积结果,实现类似倒序累加的效果。
本文详解如何将含 `ac_no` 和 `amount` 的二维数组按账户号分组,并为每组内每个元素生成“从当前项到末尾所有金额绝对值之和”的累积结果,实现类似倒序累加的效果。
在财务或账务处理场景中,常需对同一账户(如 ac_no)的多笔交易进行滚动累计计算——但不是简单求和,而是对每条记录,计算“该记录及其之后所有记录的 amount 绝对值之和”。例如:第1条记录对应全部4笔的 abs() 累加;第2条对应后3笔;第3条对应后2笔;第4条仅对应自身。
这本质上是一种倒序前缀和(reverse cumulative sum of absolute values),需分三步完成:
- 按 ac_no 分组,提取各账户的所有 amount;
- 对每组金额取绝对值,并按原始顺序保存;
- 对每组执行倒序累加:从索引 i 开始,累加 abs(amount[i]) + abs(amount[i+1]) + ... + abs(amount[end])。
以下是完整、健壮、可读性强的实现方案:
<?php $array = [
['ac_no' => 100001, 'amount' => 0.00],
['ac_no' => 100001, 'amount' => 51255.11],
['ac_no' => 100001, 'amount' => -500.00],
['ac_no' => 100001, 'amount' => -621.05],
['ac_no' => 100002, 'amount' => .00],
['ac_no' => 100003, 'amount' => .00],
['ac_no' => 100004, 'amount' => 20714.00],
['ac_no' => 100004, 'amount' => 0.00]
];
// 步骤1:按 ac_no 分组,收集所有 amount
$grouped = [];
foreach ($array as $item) {
$grouped[$item['ac_no']][] = $item['amount'];
}
// 步骤2:为每组生成倒序绝对值累加数组
$result = [];
foreach ($grouped as $acNo => $amounts) {
$absAmounts = array_map('abs', $amounts); // 全部转为绝对值
$cumulative = [];
// 倒序遍历:i=0 对应全部,i=1 对应从第2项起,依此类推
for ($i = 0; $i $acNo,
'amounts' => $amounts,
'cumulative_abs_sum' => $cumulative
];
}
// 输出格式化结果(按题设示例结构)
$output = [];
foreach ($result as $acNo => $data) {
foreach ($data['cumulative_abs_sum'] as $sum) {
$output[] = [
'ac_no' => $acNo,
'amount' => round($sum, 2) // 保留两位小数,匹配示例精度
];
}
}
print_r($output);
?>
✅ 输出示例(关键部分):
[
['ac_no' => 100001, 'amount' => 52376.16], // 0.00 + 51255.11 + 500.00 + 621.05
['ac_no' => 100001, 'amount' => 52376.16], // 51255.11 + 500.00 + 621.05
['ac_no' => 100001, 'amount' => 1121.05], // 500.00 + 621.05
['ac_no' => 100001, 'amount' => 621.05], // 621.05
['ac_no' => 100002, 'amount' => 0.0],
['ac_no' => 100003, 'amount' => 0.0],
['ac_no' => 100004, 'amount' => 20714.0],
['ac_no' => 100004, 'amount' => 0.0]
]
⚠️ 注意事项:
- 原始答案中使用 array_shift() 修改原数组会破坏数据顺序且效率较低,本方案改用 array_slice() 安全高效;
- round($sum, 2) 确保金额显示符合财务习惯(避免浮点误差导致 621.0499999999999 类问题);
- 若需严格匹配题设输出格式(如 52,376.05 带千分位),可用 number_format($sum, 2, '.', ',');
- 本逻辑不修改原始 $array,符合函数式编程原则,便于单元测试与复用。
该方案逻辑清晰、无副作用、易于扩展(如支持自定义精度、跳过零值等),适用于账务对账、余额滚动校验等典型业务场景。










