Laravel Collection 按日期分组和求和

问题描述 投票:0回答:3

我收集了需要处理才能生成报告的数据

以下是提供的数据样本

$arrival_data = [
    [
        "arrival_date" => "09-Dec-2020",
        "total_amount" => "10",
        "total_traveller" => 6
    ],
    [
        "arrival_date" => "09-Dec-2020",
        "total_amount" => "20",
        "total_traveller" => 6
    ],
    [
        "arrival_date" => "10-Dec-2020",
        "total_amount" => "40",
        "total_traveller" => 3
    ]
];

我想处理上面的数据,因此它将按“arrival_date”分组并对数据求和,以便数据如下所示

$arrival_data = [
    [
        "arrival_date" => "09-Dec-2020",
        "total_amount" => "30", // sum of 10 + 20
        "total_traveller" => 6
    ],
    [
        "arrival_date" => "10-Dec-2020",
        "total_amount" => "40",
        "total_traveller" => 3
    ]
];

我还没有设法使用 laravel 集合生成预期的输出,我能得到的最接近的输出如下

{
    "09-Dec-2020": 30,
    "10-Dec-2020": 40
}

使用下面的代码

$collection = collect($arrival_data);

$num = $collection->groupBy('arrival_date')->map(function ($row) {
    return $row->sum('total_amount');
});

return $num->toArray();

Laravel Collection 能够编写代码来按预期生成输出,或者需要通过循环数组和处理来使用不同的方法。

谢谢你

php arrays laravel laravel-collection
3个回答
7
投票

不要映射到总和,而是将要保留的字段映射到数组并对列求和并将其设置在数组中。要获取静态字段,请获取第一行,我们可以假设所有行都是相等的,因为它们已经分组。然后你将拥有与你想要实现的相同的数组结构。

$result = $collection->groupBy('arrival_date')
    ->map(function ($row) {
        $firstRow = $row->first();

        return [
            'arrival_date' => $firstRow['arrival_date'],
            'total_amount' => $row->sum('total_amount'),
            'total_traveller' => $firstRow['total_traveller'],
        ];
    })->values()
    ->all();

Group by 会将数组键映射到分组值,为了避免这种情况并收到预期结果,只需在集合上调用

->values()->all()
即可返回值。


0
投票

可能有一种更奇特的方法来处理集合,但首先想到的是一个普通的旧 foreach 循环:

$arrival_data = [
    [
        'arrival_date' => '09-Dec-2020',
        'total_amount' => '10',
        'total_traveller' => 6
    ],
    [
        'arrival_date' => '09-Dec-2020',
        'total_amount' => '20',
        'total_traveller' => 6
    ],
    [
        'arrival_date' => '10-Dec-2020',
        'total_amount' => '40',
        'total_traveller' => 3
    ]
];

$grouped_arrival_data = [];

foreach ($arrival_data as $arrival_datum) {
    if (!isset($grouped_arrival_data[$arrival_datum['arrival_date']])) {
        $grouped_arrival_data['total_amount'] = (int) $arrival_datum['total_amount'];
        $grouped_arrival_data['total_traveller'] = $arrival_datum['total_traveller'];
        $grouped_arrival_data['arrival_date'] = $arrival_datum['arrival_date'];
    } else {
        $grouped_arrival_data['total_amount'] += (int) $arrival_datum['total_amount'];
        $grouped_arrival_data['total_traveller'] += $arrival_datum['total_traveller'];
    }
}

0
投票

Laravel 的

reduce()
方法中的自定义函数是一种非常直接的方法,因为它只需一个循环即可提供所需的数组。

代码:(演示

var_export(
    $arrival_data->reduce(
        function($result, $row) {
            static $amts = [];
            if (!isset($amts[$row['arrival_date']])) {
                $amts[$row['arrival_date']] = $row;
                $result[] =& $amts[$row['arrival_date']];
            } else {
                $amts[$row['arrival_date']]['total_amount'] += $row['total_amount'];
            }
            return $result;
        }
    )
);

如果您喜欢使用大量辅助方法,这里有一种方法可以最大限度地减少本机 PHP 语法,并倾向于链接 Laravel 方法:(Demo

var_export(
    $arrival_data
    ->groupBy('arrival_date')
    ->map(fn($row) => collect($row->first())->put('total_amount', $row->sum('total_amount')))
    ->values()
    ->toArray()
);

说实话,我确实希望能够通过添加

values()
作为
false
preserveKeys
参数来省略
groupBy()
调用,但这似乎并没有删除第一级分组键。

© www.soinside.com 2019 - 2024. All rights reserved.