Search code examples
phparrayslaravelassociative-array

How to group and sum subarray items in PHP Laravel


I have N arrays. with n grade_items subarrays. just like this.

array:2 [
  0 => array:10 [
    "id" => 9
    "course_id" => 6
    "semester_id" => 2
    "name" => "Assignment"
    "total_score" => 10
    "grade_items" => array:1 [
      0 => array:7 [
        "id" => 5
        "gradelist_id" => 9
        "student_course_id" => 11
        "score" => 8
        "created_at" => "2020-04-21T03:31:20.000000Z"
        "updated_at" => "2020-04-21T20:04:10.000000Z"
      ]
    ]
  ]
  1 => array:10 [
    "id" => 10
    "course_id" => 6
    "semester_id" => 2
    "name" => "Pop Quiz"
    "total_score" => 20
    "grade_items" => array:1 [
      0 => array:7 [
        "id" => 6
        "gradelist_id" => 10
        "student_course_id" => 11
        "score" => null
        "created_at" => "2020-04-22T00:11:17.000000Z"
        "updated_at" => "2020-04-22T00:11:17.000000Z"
      ]
    ]
  ]
]

I am trying to add each grade_item subarray from each array where the student_course_id is the same. Where there is only one grade_item and no other one with the same student_course_id, then it returns just that one value instead of a sum.

I have gone through this thread

But it just messed up the logic in my head further. I've been at this for weeks.

When I add the scores from each grade_item, i want to put that value into another model say "result_model" that would look like:

result_item [
    "id" => 1,
    "student_course_id" => 11,
    "score" => 15 //total of grade_items from all arrays where the student_course_id's were the same
];

Help!


Solution

  • So basically you want to regroup the current information to receive the sum of grades. It seems the the information comes form a databases, so why don't you GROUP BY and sum on database level?

    Anyway. Here's an approach. Start by keeping a map of student_course_id => score. First it will be empty: $map = [];

    Then start iterating through the whole structure e.g. foreach ($data as $row. For each row, you need to check all the corresponding grade_items e.g. foreach ($row['grade_items'] as $gradeItem). Now you need to check whether the student_course_id from the grade item is present into the mapping.

    If it's not present, create it with starting value of zero e.g.

    if (!key_exists($gradeItem['student_course_id'], $map)) { 
        $map[$gradeItem['student_course_id']] = 0;
    }
    

    Once you ensure that the student_course_id is present, you can just add to the previous value the current score => $map[$gradeItem['student_course_id']] += $gradeItem['score'].