如何对 PHP Laravel 中的子数组项进行分组和求和

How to group and sum subarray items in PHP Laravel

我有N个数组。有 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"
      ]
    ]
  ]
]

我正在尝试从 student_course_id 相同的每个数组中添加每个 grade_item 子数组。如果只有一个 grade_item 而没有其他 student_course_id,那么它 returns 只是那个值而不是总和。

我经历过这个thread

但这只是进一步扰乱了我头脑中的逻辑。我已经在这几个星期了。

当我添加每个 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
];

求助!

使用sum()函数。您可以遍历数组,并进行任何需要的检查,例如它是否不是 Null 等,然后 pluck() 它然后 sum() 它。

所以基本上你想重新组合当前信息以获得成绩总和。信息似乎来自数据库,那么为什么不在数据库级别进行 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'].

我可以推荐递归方法吗?

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

这是我使用的示例数据

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