Re: RFC [Discussion] array_column results grouping
| From: | Hendra Gunawan | Date: | Sun, 05 Dec 2021 00:50:41 +0000 |
| Subject: | Re: RFC [Discussion] array_column results grouping | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-116568@lists.php.net to get a copy of this message | ||
>
> Hello, this is a proposal to upgrade the functionality of
>
array_column to return an indexed array for all of the matched
> data
> instead of a single result.
>
> the RFC had been created here
> https://wiki.php.net/rfc/array_column_results_grouping and the
> PR is
> in here https://github.com/php/php-src/pull/7698.
>
> However, I am not sure, if we need to add a fourth parameter to the
> function to change its behavior or we can add it as a new function,
> something like array_column_group or any other name.
>
Hai Hassan.
It seems that your proposal is just save no more than 3 lines compared with
foreach. Moreover, foreach can do better than your version.
foreach ($persons as $p) {
$groups[$p["education"]][$p["sex"]][MORE_SUBGRUP][] = $p;
}
output:
$groups = [
"elementary" => [
"female" => [
MORE_SUBGRUP_1 => [
0 => [...],
1 => [...]
],
MORE_SUBGRUP_2 => [
0 => [...],
1 => [...]
],
...
],
"male" => [
MORE_SUBGRUP_1 => [
0 => [...],
1 => [...]
],
MORE_SUBGRUP_2 => [
0 => [...],
1 => [...]
],
...
],
],
"highschool" => [
...
],
...
];
my suggestions are:
- don't limit to array => involve object as well
- offer reducer callable as an optional last param.
reducer callable it will transform 2 steps algo (populating the groups and then
reducing) to become a single step. but if it is not provided, the function
returns the member of the group (same as example above).
old way:
// step-1
$group = [];
foreach ($persons as $p) {/*...*/}
// step-2
foreach ($group as &$eduGroup) {
foreach ($eduGroup as &$sexGroup) {
$sumWeight = 0;
foreach ($sexGroup as $item) {
$sumWeight += $item->weight;
}
$sexGroup = $sumWeight / count($sexGroup);
}
}
output:
$groups = [
"elementary" => [
"female" => 40,
"male" => 50,
],
"highschool" => [
"female" => 60,
"male" => 65,
],
...
];
new way:
array_column_group(
$group,
["education", "sex", MORE_SUBGRUP],
fn ($item, $i, $cumm) => ($item->weight + ($cumm * $i)) / ($i + 1)
);
the signature:
// array_column_group signature
array_column_group(
array|object $array,
int|string|array $index_key,
callable $reducer = null
)
// callable signature
fn (array|object $item, int|string $index, mixed $cummulative): mixed
note:
- $index_key can be in the form ["education", ...] or
"education".
- or even [0, 1, ...] or 0.
So virtually, array_column_group is a hybrid between array_column and
array_walk (or other function with a funny name which I don't remember).
Best Regards
Hendra Gunawan.