Search code examples
phpmultidimensional-arraysummappinggrouping

Group and sum data from a 2d array then map totals to another 2d array


I need to sum a column of values in one array grouped by another column and map those results to another array based on a specific column value.

Sample Input:

$milestones = [
    [
        'id' => '1578453e53090b',
        'milestone' => 'Wireframe',
        'assigned_to' => 9
    ],
    [
        'id' => '1578453e530975',
        'milestone' => 'Development'
    ],
    [
        'id' => '1578453e530943',
        'milestone' => 'Design',
        'assigned_to' => 2
    ]
];

$tasks = [
    [
        'id' => '15786dc59333f2',
        'status' => 'Open',
        'progress' => 5,
        'milestone' => '1578453e53090b'
    ],
    [
        'id' => '15786dc669d451',
        'status' => 'Open',
        'progress' => 10,
        'milestone' => '1578453e53090b'
    ],
    [
        'id' => '15786dc7ccbea3',
        'status' => 'Open',
        'progress' => 20,
        'milestone' => '1578453e530943'
    ]
];

I need to get the sum of the progress values in the $tasks array grouped by milestone then store/append those totals to the $milestones array.

Desired Output:

[
    [
        'id' => '1578453e53090b',
        'milestone' => 'Wireframe',
        'assigned_to' => 9,
        'total' => 15
    ],
    [
        'id' => '1578453e530975',
        'milestone' => 'Development'
    ],
    [
        'id' => '1578453e530943',
        'milestone' => 'Design',
        'assigned_to' => 2,
        'total' => 20
    ]
]

Solution

  • One of the ways to do this is to just use foreach. Use the first foreach for the milestones getting the ID that will match the second foreach for tasks in milestone.

    After that, use a simple $total container to be used continually andatch them using a simple if.

    foreach($milestones as &$m) {
                    //     ^ add reference to make changes
        $total = 0; // initialize total holder
        foreach($tasks as $task) {
            if($task['milestone'] === $m['id']) { // if it matches
                $total += $task['progress']; // add
            }
        }
    
        $m['total'] = $total; // after its done, add another key pair being total and its value
    }