Как получить сумму из n элементов подмассива в N массивах, PHP Laravel - PullRequest
1 голос
/ 23 апреля 2020

У меня есть N массивов. с подмассивами grade_items. просто так.

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"
      ]
    ]
  ]
]

Я пытаюсь добавить каждый подмассив grade_item из каждого массива, где student_course_id одинаков. Там, где есть только один grade_item и ни один другой с таким же student_course_id, тогда он возвращает только это одно значение вместо суммы.

Я прошел этот поток

Но это только испортило логику c в моей голове дальше. Я занимаюсь этим уже несколько недель.

Когда я добавляю баллы по каждому grade_item, я хочу поместить это значение в другую модель, скажем "result_model", которая будет выглядеть следующим образом:

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
];

Помощь!

Ответы [ 4 ]

2 голосов
/ 23 апреля 2020

Таким образом, вы хотите перегруппировать текущую информацию, чтобы получить сумму оценок. Кажется, информация поступает из базы данных, так почему бы вам не выполнить GROUP BY и суммировать на уровне базы данных?

В любом случае. Вот подход. Начните с карты student_course_id => score. Сначала он будет пустым: $map = [];

Затем начните перебирать всю структуру, например foreach ($data as $row. Для каждой строки необходимо проверить все соответствующие grade_items например foreach ($row['grade_items'] as $gradeItem). Теперь вам нужно проверить, присутствует ли в отображении student_course_id из элемента оценки.

Если его нет, создайте его с начальным значением, равным нулю, например,

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

. Убедитесь, что student_course_id присутствует, вы можете просто добавить к предыдущему значению текущий счет => $map[$gradeItem['student_course_id']] += $gradeItem['score'].

1 голос
/ 23 апреля 2020

Вот пример данных, которые я использовал

$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',
                ]
            ]
        ]
    ];

и вот код;

    $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();

вот результат;

        [
            [
                'id' => 1,
                'student_course_id' => 11,
                'score' => 29,
            ],
            [
                'id' => 2,
                'student_course_id' => 15,
                'score' => 15,
            ],
            [
                'id' => 3,
                'student_course_id' => 23,
                'score' => 15,
            ]
        ]
0 голосов
/ 23 апреля 2020

Могу ли я предложить рекурсивный подход?

<?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;
?>
0 голосов
/ 23 апреля 2020

Используйте функцию sum(). Вы можете l oop через массив и делать любые необходимые проверки, например, если это не Null et c, и собирать (), а затем суммировать ().

...