2

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!

6
  • where does the id come from the result model - i understand student_course_id and score (sum of same course ids ) but didn't get id Commented Apr 23, 2020 at 0:19
  • It's automatically generated when I create a new instance of the model. I just gave a structure to what it should look like after the model is saved. Commented Apr 23, 2020 at 0:23
  • Like when it checks the first grade_item in the first array, It would search through other arrays(not that sub array), for other grade_items with the same student_course_id and add the scores together. Then create a new result_item with the student_course_id and the computed score. Commented Apr 23, 2020 at 0:29
  • asking to clarify, at the end of the day; you want the sum of scores which are grouped by student_course_id right ? Commented Apr 23, 2020 at 0:31
  • yeah, exactly. but across the arrays not just within the subarrays. Commented Apr 23, 2020 at 0:34

4 Answers 4

2

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'].

Sign up to request clarification or add additional context in comments.

4 Comments

Hmmm! this is a very good approach. I'd try it out now and get back to you. What you said about regrouping it and summing on database level got my attention too. I will look into that also.
This worked! So I took your advice and regrouped and summed on database level. So I got all the grade_items from the arrays I was interested in and groupedBy the student_course_id then looped through each group and got the sum, then I instantiated the result_item model and saved the score as the sum of the group.
So my grouping looked like this ``` array:1 [ 11 => array:2 [ 0 => array:7 [ "id" => 5 "gradelist_id" => 9 "student_course_id" => 11 "score" => 8 ] 1 => array:7 [ "id" => 6 "gradelist_id" => 10 "student_course_id" => 11 "score" => 0 ] ] ] ```
then I did this. ``` foreach ($grade_items as $key => $grade_item) { $sum = $grade_item->sum('score'); $result_item = new ResultItem(); $result_item->student_course_id = $key; $result_item->score = $sum; $result_item->save(); } ```
1

Here is a sample data i used

$array = [
        [
            'id' => 9,
            'course_id' => 6,
            'semester_id' => 2,
            'name' => 'Assignment',
            'total_score' => 10,
            'grade_items' => [
                [
                    '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',
                ],
                [
                    'id' => 5,
                    'gradelist_id' => 9,
                    'student_course_id' => 15,
                    'score' => 15,
                    'created_at' => '2020-04-21T03:31:20.000000Z',
                    'updated_at' => '2020-04-21T20:04:10.000000Z',
                ]
            ]
        ],
        [
            'id' => 10,
            'course_id' => 6,
            'semester_id' => 2,
            'name' => 'Pop Quiz',
            'total_score' => 20,
            'grade_items' => [
                [
                    'id' => 6,
                    'gradelist_id' => 10,
                    'student_course_id' => 11,
                    'score' => 21,
                    'created_at' => '2020-04-22T00:11:17.000000Z',
                    'updated_at' => '2020-04-22T00:11:17.000000Z',
                ],
                [
                    'id' => 6,
                    'gradelist_id' => 10,
                    'student_course_id' => 23,
                    'score' => 15,
                    'created_at' => '2020-04-22T00:11:17.000000Z',
                    'updated_at' => '2020-04-22T00:11:17.000000Z',
                ]
            ]
        ]
    ];

and here is the code;

    $id = 0;

    return collect($array)
        ->flatMap(function ($item){
            return $item['grade_items'];
        })
        ->groupBy('student_course_id')
        ->transform(function ($subItems, $courseId) use (&$id) {
            $id++;

            return [
                'id' => $id,
                'student_course_id' => $courseId,
                'score' => $subItems->sum('score')
            ];
        })
        ->values()
        ->toArray();

here is the result;

        [
            [
                'id' => 1,
                'student_course_id' => 11,
                'score' => 29,
            ],
            [
                'id' => 2,
                'student_course_id' => 15,
                'score' => 15,
            ],
            [
                'id' => 3,
                'student_course_id' => 23,
                'score' => 15,
            ]
        ]

Comments

0

Use the sum() function. You can loop through the array, and do any checks you need, like if it is not Null etc, and pluck() it and then sum() it.

1 Comment

Doing this would only give me access to the subarray in an array and not across all arrays. I want to sum values from the two arrays, not within the subarray. Like. sum all the grade_items in all arrays where the student_course_id's are equal.
0

May I suggest recursivity approach?

<?php 
    function rec_sum_grades(&$array_grades, &$sum = 0){
      $sum += $array_grades['total_score'];
      if(!empty($array_grades['grade_items'])){
      $this->rec_sum_grades($array_grades['grade_items'], $sum);
    }
  }
  rec_sum_grades($array_grades, $sum);
  echo $sum;
?>

1 Comment

Hmmm... the issue here is that it would add across grade_items with different student_course_id's instead of items with the same student_course_id. But after grouping the grade_items by student_course_id, then this would work for me. Thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.