
在企业应用开发中,我们经常面临需要对数据进行聚合和汇总的场景。例如,在一个交付单系统中,用户可能会输入同一批次、同一类型和尺寸的商品多次,但最终在交付单上,我们需要将这些重复的条目合并,并显示它们的总数量。这不仅能提高数据可读性,也符合业务逻辑。
假设我们有以下原始数据结构,代表了圣诞树的销售明细,其中 line_items 是一个包含多个商品条目的集合:
[
{
"slot": 2,
"pallet": "cghjh",
"type": "NGR",
"label": "purple",
"size": "125-150",
"amount": "30"
},
{
"slot": 3,
"pallet": "cghjh",
"type": "NGR",
"label": "purple",
"size": "125-150",
"amount": "30"
},
{
"slot": 2,
"pallet": "yghiuj",
"type": "NGR",
"label": "orange",
"size": "150-175",
"amount": "30"
},
{
"slot": 3,
"pallet": "cghjh",
"type": "NOB",
"label": "purple",
"size": "125-150",
"amount": "30"
}
]我们的目标是将其转换为以下聚合后的结构,其中 type 和 size 相同的条目被合并,amount 字段被求和,并且移除了 slot, pallet, label 等不必要的详细信息:
{
"NGR": {
"125-150": [
{
"type": "NGR",
"size": "125-150",
"amount": 60
}
],
"150-175": [
{
"type": "NGR",
"size": "150-175",
"amount": 30
}
]
},
"NOB": {
"125-150": [
{
"type": "NOB",
"size": "125-150",
"amount": 30
}
]
}
}Laravel Collection 提供了强大的数据处理能力。首先,我们可以使用 groupBy 方法对数据进行多层分组。根据我们的需求,我们可以先按 type 分组,再按 size 分组:
use Illuminate\Support\Collection;
// 假设 $deliveryNote->line_items 是一个包含上述JSON数据的数组或Collection
$data = collect($deliveryNote->line_items)
->groupBy(['type', 'size']);执行上述代码后,$data 将会得到一个嵌套的 Collection 结构,大致如下:
{
"NGR": {
"125-150": [
{
"slot": 2,
"pallet": "cghjh",
"type": "NGR",
"label": "purple",
"size": "125-150",
"amount": "30"
},
{
"slot": 3,
"pallet": "cghjh",
"type": "NGR",
"label": "purple",
"size": "125-150",
"amount": "30"
}
],
"150-175": [
{
"slot": 2,
"pallet": "yghiuj",
"type": "NGR",
"label": "orange",
"size": "150-175",
"amount": "30"
}
]
},
"NOB": {
"125-150": [
{
"slot": 3,
"pallet": "cghjh",
"type": "NOB",
"label": "purple",
"size": "125-150",
"amount": "30"
}
]
}
}这个结构已经非常接近我们想要的结果,它将相同 type 和 size 的条目归并到了一起。然而,我们还需要进一步处理,包括求和 amount 字段并精简每个条目的字段。
直接在 groupBy 之后使用 map 并尝试 sum('amount') 是行不通的,因为 groupBy 返回的是一个嵌套的 Collection。例如,以下尝试并不能得到正确的结果:
// 这是一个错误的尝试,无法达到预期效果
$data = collect($deliveryNote->line_items)
->groupBy(['type', 'size'])
->map(function ($item) {
// 这里的 $item 是一个 Collection,其键是 size,值是 size 对应的条目集合
// 直接 sum('amount') 会失败,因为它没有深入到最内层
return $item->sum('amount');
});上述代码只会遍历第一层分组(type 的键),而无法深入到 size 对应的具体商品条目中去求和。我们需要一种方法来遍历所有分组层级,并在最内层执行聚合操作。
解决这个问题的关键在于利用 Collection 的链式调用和嵌套 map 方法,逐层深入到分组的最低层级进行处理。
核心思路:
完整代码示例:
use Illuminate\Support\Collection;
// 假设 $deliveryNote->line_items 是一个包含上述JSON数据的数组或Collection
$aggregatedData = collect($deliveryNote->line_items)
->groupBy(['type', 'size']) // 第一步:按 type 和 size 进行分组
->map(function (Collection $typeGroups) { // 第二步:遍历外层分组(按 type)
// $typeGroups 是一个 Collection,其中键是 'size',值是该 type 和 size 的所有条目
return $typeGroups->map(function (Collection $sizeGroup) { // 第三步:遍历内层分组(按 size)
// $sizeGroup 是一个 Collection,其中包含所有具有相同 type 和 size 的原始条目
return [
'type' => $sizeGroup->first()->type, // 从第一个条目获取 type
'size' => $sizeGroup->first()->size, // 从第一个条目获取 size
'amount' => $sizeGroup->sum('amount'), // 对所有条目的 amount 字段求和
];
});
});代码解析:
执行上述代码后,$aggregatedData 将会得到我们期望的精简且聚合后的数据结构。
通过本教程,我们学习了如何利用 Laravel Collection 的 groupBy 和嵌套 map 方法,优雅地处理多层分组后的数据聚合需求。这种方法不仅能够合并重复项,对特定字段进行求和,还能精简数据结构,使其更符合业务展示要求。掌握这些 Collection 操作技巧,将大大提升你在 Laravel 应用中处理复杂数据逻辑的能力。
以上就是Laravel Collection:多层分组后合并重复项并求和特定字段的教程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号