【问题标题】:How to group and sum subarray items in PHP Laravel如何在 PHP Laravel 中对子数组项进行分组和求和
【发布时间】:2020-08-06 04:06:16
【问题描述】:

我有 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 的项目,则它只返回一个值而不是总和。

我经历过这个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
];

救命!

【问题讨论】:

  • id 来自结果模型的哪里 - 我了解 student_course_id 和分数(相同课程 id 的总和)但没有得到 id
  • 它是在我创建模型的新实例时自动生成的。我只是给出了模型保存后的结构。
  • 就像检查第一个数组中的第一个grade_item一样,它会搜索其他数组(不是那个子数组),寻找具有相同student_course_id的其他grade_item并将分数相加。然后使用 student_course_id 和计算的分数创建一个新的 result_item。
  • 在一天结束时要求澄清;你想要按 student_course_id 分组的分数总和吗?
  • 是的,没错。但不仅仅是在子数组中。

标签: php arrays laravel associative-array


【解决方案1】:

这是我使用的示例数据

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

【讨论】:

    【解决方案2】:

    我可以建议递归方法吗?

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

    【讨论】:

    • 嗯...这里的问题是它会添加具有不同 student_course_id 的grade_items,而不是具有相同 student_course_id 的项目。但是在按 student_course_id 对grade_items 进行分组之后,这对我有用。谢谢!
    【解决方案3】:

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

    【讨论】:

    • 嗯!这是一个非常好的方法。我现在就试试,然后回复你。你所说的关于重新组合它并在数据库级别求和的内容也引起了我的注意。我也会调查的。
    • 这成功了!因此,我接受了您的建议,并在数据库级别进行了重新组合和总结。所以我从我感兴趣的数组中得到了所有grade_items,并通过student_course_id 进行分组,然后遍历每个组并得到总和,然后我实例化result_item 模型并将分数保存为组的总​​和。
    • 所以我的分组看起来像这样 ``` array:1 [ 11 => array:2 [ 0 => array:7 [ "id" => 5 "gradelist_id" => 9 "student_course_id" => 11 “分数” => 8 ] 1 => 数组:7 [ “id” => 6 “gradelist_id” => 10 “student_course_id” => 11 “分数” => 0 ] ] ``
    • 然后我就这样做了。 ``` 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->保存(); } ```
    【解决方案4】:

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

    【讨论】:

    • 这样做只会让我访问数组中的子数组,而不是访问所有数组。我想对两个数组中的值求和,而不是在子数组中。喜欢。将 student_course_id 相等的所有数组中的所有 Grade_items 相加。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-06
    • 1970-01-01
    • 2011-02-15
    相关资源
    最近更新 更多