5分钟前分组收集laravel

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

我有一个由11:47到12:17的数据组成的Laravel集合:

Illuminate\Support\Collection Object
(
    [items:protected] => Array

        (
            [2020-03-17 11:47:00] => Array
                (
                    [avg] => 4.0666666666667
                )

            [2020-03-17 11:48:00] => Array
                (
                    [avg] => 4.8095238095238
                )

            ...

            [2020-03-17 12:17:00] => Array
                (
                    [avg] => 1
                )

        )
)

我需要帮助将这个集合从第一个日期开始按5分钟分组. 如果我尝试这样分组:

$groupedBy5Minutes = $collection->groupBy(function ($item, $key) {
    return Carbon::parse($key)->timestamp - Carbon::parse($key)->timestamp % (300);
});

我得到的结果是从11:45(11:45-12:15)开始, 而不是11:47(11:47:12:17)开始按5分钟分组.

laravel grouping php-carbon
1个回答
1
投票

首先,我复制了你的集合,如下。avg是一个随机数

$period = Carbon::parse('2020-03-17 11:47:00')->toPeriod('2020-03-17 12:17:00', 1, 'minutes')->toArray();
/* 
[
    '2020-03-17 11:47:00',
    '2020-03-17 11:48:00',
    ...,
    '2020-03-17 12:17:00'
]
*/

$collection = collect($period)->mapWithKeys(fn($item) =>
    [$item->format('Y-m-d H:i:s') => ['avg' => rand(1,1000)]]
);
/*
Illuminate\Support\Collection {
    all: [    
        '2020-03-17 11:47:00' => ['avg' => 134],
        '2020-03-17 11:48:00' => ['avg' => 545],
        ...,
        '2020-03-17 12:17:00' => ['avg' => 654]
    ]
}
*/

为了得到你想要的东西,有一个小技巧,你可以用Carbon的地板功能。

$interval = Carbon::parse($collection->keys()->first())
  ->floorMinutes(5)
  ->diff($collection->keys()->first());

$grouped = $collection->groupBy(fn($item, $key) =>
    Carbon::parse($key)
    ->floorMinutes(5)
    ->add($interval)
    ->format('Y-m-d H:i:s')
);
// Using classic closures
$grouped = $collection->groupBy(function ($item, $key) use ($interval) {
    return Carbon::parse($key)
    ->floorMinutes(5)
    ->add($interval)
    ->format('Y-m-d H:i:s');
});
/*
Illuminate\Support\Collection {
    all: [    
        '2020-03-17 11:47:00' => Illuminate\Support\Collection {
            all: [
                ['avg' => 134],
                ['avg' => 545],
                ['avg' => 232],
                ['avg' => 654],
                ['avg' => 123]
            ]
        },
        '2020-03-17 11:52:00' => Illuminate\Support\Collection {
            all: [
                ['avg' => 463],
                ['avg' => 765],
                ['avg' => 732],
                ['avg' => 464],
                ['avg' => 512]
            ]
        },
        ...,
        '2020-03-17 12:17:00' => Illuminate\Support\Collection {
            all: [
                ['avg' => 873],
                ['avg' => 797],
                ['avg' => 694],
                ['avg' => 754],
                ['avg' => 654]
            ]
        }
    ]
}
*/

基本上,我们是按5分钟的时间间隔来分组(11: 45, 11: 50, ..., 12: 15),但在每个键上加上第一个键(11: 47)和最后5分钟(11: 45)的浮动值之间的差值。

11:45 + (11:47 - 11:45) = 11:47
11:50 + (11:47 - 11:45) = 11:52
11:55 + (11:47 - 11:45) = 11:57
12:00 + (11:47 - 11:45) = 12:02

1
投票

如果您只需要数值,您可以使用 diffInMinutes:

$first = $collection->keys()->first();

$grouped = $collection->groupBy(fn($item, $key) =>
    (int) floor(Carbon::parse($key)->diffInMinutes($first) / 5)
);

如果您需要参考开始日期,那么 IGP解决方案 是正确的做法。

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