skip to Main Content

Hello I’ve got two arrays, one which is made with Carbon that takes the last 12 months from today (in Y-m format) and a Collection (which have an array of items that return every transaction of the last 12 months in the same Y-m format). What I want to do is fill in this items array if there’s no transaction for example on the month 12, 9, 8 fill them with 0.

Here’s the 2 arrays I need compared and fill missing Year-month with 0 (the last array is the balance which will be merged into the array for every month).

^ 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
]

The code I used at the moment to find the balance per month (the latest balance of the month) but at the moment I dont print the missing months (it just skips them instead of filling with 0):

$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);

At the moment I achieved printing the balance of the oldest day of the month on the last 12 months, what Im missing is comparing if of this 12 months if there’s a month missing fill it with 0 instead of skipping it.

2

Answers


  1. Chosen as BEST ANSWER

    Improved the code to this:

    $months = CarbonPeriod::create(now()->subMonths(11), now())->month();
            
                                    $transactions = auth()->user()->transactions
                                                    ->groupBy( fn($d) => Carbon::parse( $d->created_at )->format('Y-m'))->map->last();
                                    
                                    $transactionsByMonth = collect($months)
                                            ->flatMap(function ($key) use ($transactions) {
                                                $key = $key->format('Y-m');
                                                return [$key => collect($transactions[$key]->main_balance ?? 0)];
                                            });
                                    $transactionsByMonth = $transactionsByMonth->toArray();
                                    $transactionsByMonth = array_values($transactionsByMonth);
                                    dump($transactionsByMonth);
        
       
    
     But Im getting an array inside an array:
        
           array:12 [▼
              0 => array:1 [▼
                0 => 480
              ]
              1 => array:1 [▼
                0 => 550
              ]
              2 => array:1 [▼
                0 => 690
              ]
              3 => array:1 [▶]
              4 => array:1 [▶]
              5 => array:1 [▶]
              6 => array:1 [▶]
              7 => array:1 [▶]
              8 => array:1 [▶]
              9 => array:1 [▶]
              10 => array:1 [▶]
              11 => array:1 [▶]
            ]
    

    So What I finally did to solve it was instead of returning the collect() for every $key I just returned the collect directly so I would stop getting an array inside an array.

    Replaced this:

        $transactionsByMonth = collect($months)
                                        ->flatMap(function ($key) use ($transactions) {
                                            $key = $key->format('Y-m');
                                            return [$key => collect($transactions[$key]->main_balance ?? 0)];
                                        });
                                $transactionsByMonth = $transactionsByMonth->toArray();
                                $transactionsByMonth = array_values($transactionsByMonth);
                                dump($transactionsByMonth);
    

    Into this:

        $transactionsByMonth = collect($months)
                                        ->flatMap(function ($key) use ($transactions) {
                                            $key = $key->format('Y-m');
                                            return collect($transactions[$key]->main_balance ?? 0);
                                        });
                                $transactionsByMonth = $transactionsByMonth->toArray();
    

  2. You can use array_key_exists() function to compare the two arrays and fill in missing months with 0.
    Example:

    $carbonMonths = ["2022-01", "2022-02", "2022-03", "2022-04", "2022-05", "2022-06", "2022-07", "2022-08", "2022-09", "2022-10", "2022-11", "2022-12"];
    $transactions = [
        ["2022-01" => 200],
        ["2022-02" => 150],
        ["2022-03" => 100],
        ["2022-05" => 50]
    ];
    
    foreach ($carbonMonths as $month) {
        if (!array_key_exists($month, $transactions)) {
            $transactions[$month] = 0;
        }
    }
    

    In this example, the $carbonMonths array contains the last 12 months in Y-m format. The $transactions array contains transactions in the same format.

    You can also use the array_merge() function to merge the two arrays and fill in any missing values with 0.

    $merged = array_merge(array_fill_keys($carbonMonths, 0), $transactions);
    

    Here $transactions should be an associative array with keys as month and value for this to work.

    Both of the approach should give you the same result, you may use the one which you find easy to implement.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search