如何用Carbon补全缺失月份的交易余额数组并填充0
问题解决:填充缺失交易月份的余额为0
我有三个数组:
- 用Carbon生成的、以
Y-m格式表示的近12个月数组; - 交易记录集合分组后得到的同格式数组;
- 需要和月份数组合并的余额数组。
目前已实现获取有交易记录月份的每月最后一天余额,但缺失交易记录的月份会被跳过,需将这些月份的余额填充为0。
相关数组示例
// 近12个月数组(默认填充0) ^ array:12 [▼ "2022-02" => 0 "2022-03" => 0 "2022-04" => 0 "2022-05" => 0 "2022-06" => 0 "2022-07" => 0 "2022-08" => 0 "2022-09" => 0 "2022-10" => 0 "2022-11" => 0 "2022-12" => 0 "2023-01" => 0 ] // 交易记录分组数组 ^ array:12 [▼ "2022-01" => 0 "2022-02" => 1 "2022-03" => 2 "2022-04" => 3 "2022-06" => 4 "2022-07" => 5 "2022-08" => 6 "2022-09" => 7 "2022-10" => 8 "2022-11" => 9 "2022-12" => 10 "2023-01" => 11 ] // 余额数组 ^ array:12 [▼ 0 => 340 1 => 480 2 => 550 3 => 690 4 => 830 5 => 970 6 => 1110 7 => 1250 8 => 1460 9 => 1600 10 => 1670 11 => 1880 ]
现有实现代码
$period = CarbonPeriod::create(now()->subMonths(11), now())->month(); $dates = array(); $days = array(); foreach($period as $date) { $dates[] = $date->format("Y-m"); $days[] = $date->lastOfMonth()->format("d-m-Y"); } $userTransactions = auth()->user()->transactions; $flipped = array_flip($dates); $transactionsByMonth = $userTransactions->groupBy(function($d) { $monthlyTransaction = Carbon::parse($d->created_at)->format('Y-m'); return $monthlyTransaction; }); foreach($flipped as $key => $yearMonth){ $yearMonth = 0; $flipped[$key] = $yearMonth; } dump($flipped); foreach($transactionsByMonth as $transaction) { if (sizeof($transaction) > 1){ $duplicatedTransactions = $transaction->groupBy(function($d) { return Carbon::parse($d->created_at)->format('Y-m-d'); }); $lastDuplicatedTransactions = $duplicatedTransactions->last(); foreach($lastDuplicatedTransactions as $lastTransaction){ $transactionDates[] = $lastTransaction->created_at; $transactionBalance[] = $lastTransaction->main_balance; } } else { foreach($transaction as $notDuplicatedTransaction){ $transactionDates[] = $notDuplicatedTransaction->created_at; $transactionBalance[] = $notDuplicatedTransaction->main_balance; } } }; $transactionsPerMonth = []; foreach($transactionDates as $date){ $date = Carbon::parse($date)->format('Y-m'); $transactionsPerMonth[] = $date; } $transactionsPerMonth = array_flip($transactionsPerMonth); dump($transactionsPerMonth); dump($transactionBalance);
优化解决方案
核心思路是先基于完整的近12个月数组生成默认余额为0的结构,再用有交易记录的月份余额覆盖对应位置,缺失月份自动保留0。
修改后的完整代码
$period = CarbonPeriod::create(now()->subMonths(11), now())->month(); $dates = []; $days = []; foreach($period as $date) { $dates[] = $date->format("Y-m"); $days[] = $date->lastOfMonth()->format("d-m-Y"); } $userTransactions = auth()->user()->transactions; // 1. 生成包含所有近12个月、默认余额为0的数组 $monthlyBalances = array_fill_keys($dates, 0); // 2. 按月份分组交易记录 $transactionsByMonth = $userTransactions->groupBy(function($d) { return Carbon::parse($d->created_at)->format('Y-m'); }); // 3. 遍历有交易的月份,更新对应余额 foreach($transactionsByMonth as $month => $transactions) { // 按日期分组,获取每月最后一天的交易 $dailyTransactions = $transactions->groupBy(function($d) { return Carbon::parse($d->created_at)->format('Y-m-d'); }); $lastDayTransactions = $dailyTransactions->last(); if ($lastDayTransactions) { // 取最后一天的最后一笔交易余额(同一天余额应一致) $lastBalance = $lastDayTransactions->last()->main_balance; // 仅当该月份在目标列表中时更新 if (isset($monthlyBalances[$month])) { $monthlyBalances[$month] = $lastBalance; } } } // 最终结果:按近12个月顺序,缺失月份已填充0 dump($monthlyBalances);
代码说明
- 用
array_fill_keys直接生成完整月份的余额数组,默认值为0,省去后续补全缺失项的麻烦; - 简化交易处理逻辑,直接按日期分组取每月最后一天的交易,再提取余额;
- 仅更新有交易记录的月份余额,无交易的月份保持默认0值。
内容的提问来源于stack exchange,提问作者Ignacio
相关产品推荐
相关产品推荐

