我有一个由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分钟分组.
首先,我复制了你的集合,如下。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
如果您只需要数值,您可以使用 diffInMinutes
:
$first = $collection->keys()->first();
$grouped = $collection->groupBy(fn($item, $key) =>
(int) floor(Carbon::parse($key)->diffInMinutes($first) / 5)
);
如果您需要参考开始日期,那么 IGP解决方案 是正确的做法。