按 5 分钟收集 laravel 组
Group laravel collection by 5 minutes
我有 Laravel 个集合,包含从 11:47 到 12:17 的数据:
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);
});
我得到的结果按 5 分钟分组,但从 11:45 (11:45-12:15) 而不是 11:47 (11:47:12:17 ).
首先,我将您的合集转载如下。平均值是一个随机数
$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 的 floor 函数中使用一些技巧:
$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)
);
如果您需要保留对开始日期的引用,那么 是正确的方法。
我认为这是另一种方法。
// hours grouped by key, in this case every 6 hours.
$intervals = collect([
5 => [0,1,2,3,4,5],
11 => [6,7,8,9,10,11],
17 => [12,13,14,15,16,17],
23 => [18,19,20,21,22,23],
]);
$balances = $balances
->get()
->groupBy(function($balance) use ($intervals) {
$created_at = Carbon::parse($balance->created_at);
$hour = $created_at->hour;
$mapped_interval = $intervals
->filter(function($collection) use ($hour) {
return in_array($hour, $collection);
})
->keys()
->first();
return $created_at->format("Ymd") . $mapped_interval; // grouping it
});
我有 Laravel 个集合,包含从 11:47 到 12:17 的数据:
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);
});
我得到的结果按 5 分钟分组,但从 11:45 (11:45-12:15) 而不是 11:47 (11:47:12:17 ).
首先,我将您的合集转载如下。平均值是一个随机数
$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 的 floor 函数中使用一些技巧:
$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)
);
如果您需要保留对开始日期的引用,那么
我认为这是另一种方法。
// hours grouped by key, in this case every 6 hours.
$intervals = collect([
5 => [0,1,2,3,4,5],
11 => [6,7,8,9,10,11],
17 => [12,13,14,15,16,17],
23 => [18,19,20,21,22,23],
]);
$balances = $balances
->get()
->groupBy(function($balance) use ($intervals) {
$created_at = Carbon::parse($balance->created_at);
$hour = $created_at->hour;
$mapped_interval = $intervals
->filter(function($collection) use ($hour) {
return in_array($hour, $collection);
})
->keys()
->first();
return $created_at->format("Ymd") . $mapped_interval; // grouping it
});