Search code examples
phparraysforeachsumgrouping

Group every three rows in a 2d array and sum one column


I need to group 3 rows together, sum their salary values and access the month name from the next row (next calendar month).

$salaries =
[
    [
        'month'=>'January',
        'salary'=>200
    ],
    [
        'month'=>'Februray',
        'salary'=>300
    ],
    [
        'month'=>'March',
        'salary'=>400
    ],
    [
        'month'=>'April',
        'salary'=>500
    ],
    [
        'month'=>'May',
        'salary'=>600
    ],
    [
        'month'=>'June',
        'salary'=>700
    ],
    [
        'month'=>'July',
        'salary'=>800
    ],
    [
        'month'=>'August',
        'salary'=>900
    ],
    [
        'month'=>'September',
        'salary'=>1000
    ],
    [
        'month'=>'October',
        'salary'=>1100
    ],
    [
        'month'=>'November',
        'salary'=>130
    ],
    [
        'month'=>'December',
        'salary'=>1200
    ]
];

I tried the code on this page, but I don't know how to specify the 4th month with the sum.

If possible, I want this:

Array
(
    [0] => 
[
'month'=>'April'
'sum'=900
]
    [1] => 
[
'month'=>'other month'
'sum'=1800
]
    [2] => 
[
'month'=>'other month'
'sum'=2700
]
    [3] => 
[
'month'=>'other month'
'sum'=2430
]
)

I tried with this code:

$groupSum = []; 
foreach (array_chunk($salaries , 3) as $key => $value) { 
    $groupSum[] = array_reduce($value, function ($sum, $item) { 
        $sum += $item['salary']; return $sum; 
    }); 
}

And the result is :

Array ( 
    [0] => 900
    [1] => 1800
    [2] => 2700
    [3] => 2430
)

Solution

  • A (very) basic solution (for my tests, I fix the typo on February month name) :

    function getNextMonth($month) {
        $months = ['January','February','March','April','May','June','July','August','September','October','November','December'];
    
        $pos = array_search($month, $months);
    
        if ($pos === false) {
            throw new Exception('Invalid month');
        }
    
        if ($pos == 11) {
            return 'January';
            // should return also year + 1
        }
    
        return $months[$pos+1];
    }
    
    $i = 1;
    $trimestreSum = 0;
    $trimestres = [];
    foreach($salaries as $month) {
        $trimestreSum += $month['salary'];
        if ($i % 3 == 0) {
            array_push($trimestres, [
                'month' => getNextMonth($month['month']),
                'sum' => $trimestreSum,
            ]);
            $i = 0;
            $trimestreSum = 0;
        }
        $i++;
    
    }
    
    print_r($trimestres);
    

    The result is

        Array
    (
        [0] => Array
            (
                [month] => April
                [sum] => 900
            )
        [1] => Array
            (
                [month] => July
                [sum] => 1800
            )
        [2] => Array
            (
                [month] => October
                [sum] => 2700
            )
        [3] => Array
            (
                [month] => January
                [sum] => 2430
            )
    )
    

    The getNextMonth may be the only piece of code you need to add to your own code :)

    Pretty sure that there are shorter (and more elegant) solutions, but hope that helps anyway.