You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 如何对groupBy结果使用reduce高效统计供应商总金额

优化后实现方案

完全使用Laravel集合内置方法,不需要手动嵌套循环,性能和可读性都优于原有实现:

// 注意原方法名generateSupplierDate是笔误,修正为generateSupplierData更合理
private function generateSupplierData(Collection $collection, array $suppliers = []): Collection
{
    return $collection->pluck('items')
        ->flatten()
        ->whereIn('supplier', $suppliers)
        ->groupBy('supplier')
        ->map(function ($group, $supplierName) {
            return [
                'supplier' => $supplierName,
                'totalCost' => $group->sum('quantity')
            ];
        })
        ->values();
}

逻辑说明

  1. 原代码存在隐性问题:方法声明返回Collection类型,但最终返回了普通数组,运行时会抛出类型错误,优化后的代码直接返回集合实例完全符合声明要求。
  2. 原有打平数组、过滤指定供应商的逻辑保留,这部分是必要的前置处理。
  3. 按supplier分组后直接调用集合的sum()方法对分组内的quantity字段求和,不需要手动循环累加,Laravel底层优化过的聚合方法执行效率优于手动嵌套循环,代码可读性也更高。
  4. 用map()方法直接把分组转换成你需要的键名格式,最后调用values()重置数组键为连续的数字索引,返回的集合转JSON后和你要求的输出结构完全匹配。

reduce实现版本(性能更高)

如果你需要用reduce实现的话可以参考以下写法,整个过程只需要一次遍历,不需要分组阶段,性能会略高于分组实现:

private function generateSupplierData(Collection $collection, array $suppliers = []): Collection
{
    return $collection->pluck('items')
        ->flatten()
        ->whereIn('supplier', $suppliers)
        ->reduce(function ($carry, $item) {
            // 查找当前供应商是否已经在结果中存在
            $exists = $carry->firstWhere('supplier', $item->supplier);
            if ($exists) {
                $exists['totalCost'] += $item->quantity;
            } else {
                $carry->push([
                    'supplier' => $item->supplier,
                    'totalCost' => $item->quantity
                ]);
            }
            return $carry;
        }, collect());
}

你有JS开发基础的话理解起来会很简单,Laravel集合的方法逻辑和JS数组方法基本一致,只是部分API命名有差异,reduce的用法和JS几乎完全相同,只是初始值需要用collect()生成空集合而非空数组。

内容的提问来源于stack exchange,提问作者Riza Khan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 09:15:04