You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 03:01:07