3, "marks" => 10], ["studentId" => 7, "marks" => 15] ], [ ["studentId" => 3, "marks" /> 3, "marks" => 10], ["studentId" => 7, "marks" => 15] ], [ ["studentId" => 3, "marks" /> 3, "marks" => 10], ["studentId" => 7, "marks" => 15] ], [ ["studentId" => 3, "marks"/>

Laravel sum up values from multidimensional array collection

195 Views Asked by At

I have a collection like

$collection = collect([
   [
      ["studentId" => 3, "marks" => 10],
      ["studentId" => 7, "marks" => 15]
   ],
   [
      ["studentId" => 3, "marks" => 20],
      ["studentId" => 7, "marks" => 15]
   ],
   [
      ["studentId" => 3, "marks" => 10],
      ["studentId" => 7, "marks" => 20]
   ],
]);

I want to sum up marks for specific studentId and map the results like

[
   ["studentId" => 3, "marks" => 40],
   ["studentId" => 7, "marks" => 50],
]

Thanks

1

There are 1 best solutions below

0
Levi Cole On BEST ANSWER

This is untested but you can probably do something like...

$collection = collect([
   [
      ['studentId' => 3, 'marks' => 10],
      ['studentId' => 7, 'marks' => 15]
   ],
   [
      ['studentId' => 3, 'marks' => 20],
      ['studentId' => 7, 'marks' => 15]
   ],
   [
      ['studentId' => 3, 'marks' => 10],
      ['studentId' => 7, 'marks' => 20]
   ],
]);

$collection = $collection
    ->flatten(1)
    ->groupBy('studentId')
    ->transform(function($subItems, $studentId) {
        return [
            'studentId' => $studentId,
            'marks' => $subItems->sum('marks')
        ];
    })
    ->values();

What this does is...

1. Flatten the array

First we flatten the collection by 1 depth using the flatten method. Resulting structure...

[
  ['studentId' => 3, 'marks' => 10],
  ['studentId' => 7, 'marks' => 15],
  ['studentId' => 3, 'marks' => 20],
  ['studentId' => 7, 'marks' => 15],
  ['studentId' => 3, 'marks' => 10],
  ['studentId' => 7, 'marks' => 20]
]

2. Group values by

Next we group all the values by the studentId using the groupBy method. Result...

[
  3 => [
    ['studentId' => 3, 'marks' => 10],
    ['studentId' => 3, 'marks' => 20],
    ['studentId' => 3, 'marks' => 10]
  ],
  7 => [
    ['studentId' => 7, 'marks' => 15],
    ['studentId' => 7, 'marks' => 15],
    ['studentId' => 7, 'marks' => 20]
  ]
]

3. Sum the marks

Now we calculate the groups of marks with the transform method. Result...

[
  3 => ['studentId' => 3, 'marks' => 40],
  7 => ['studentId' => 7, 'marks' => 50]
]

4. Reset keys (optional)

You'll notice in the last result that the top level array keys are the same as the studentId values this is left over from the groupBy method. We can reset these with the values method. Result...

[
  ['studentId' => 3, 'marks' => 40],
  ['studentId' => 7, 'marks' => 50]
]