Re: [RFC] [Discussion] Add new function `array_group`
| From: | Andreas Hennings | Date: | Tue, 30 May 2023 16:25:21 +0000 |
| Subject: | Re: [RFC] [Discussion] Add new function `array_group` | ||
| References: | 1 2 3 4 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-120463@lists.php.net to get a copy of this message | ||
Here we go,
https://3v4l.org/KsL3o
function array_group(array $arr1, callable $compare): array {
$groups = [];
$group = [];
$prev = NULL;
foreach ($arr1 as $value) {
if ($group && !$compare($prev, $value)) {
$groups[] = $group;
$group = [];
}
$group[] = $value;
$prev = $value;
}
if ($group) {
$groups[] = $group;
}
return $groups;
}
On Tue, 30 May 2023 at 18:21, Andreas Hennings <andreas@dqxtech.net> wrote:
>
> Thank you, this clarifies and it confirms my initial assumption of
> what you are proposing.
> So you want to slice an array by comparing adjacent values.
>
>
> My personal feedback:
> I think the need for the grouping behavior you describe is not common
> enough that it needs its own native function.
> I would say the more common desired behavior is the one in your first
> example. And even for that we don't have a native function.
>
> Your behavior can be implemented in userland like so:
> https://3v4l.org/epvHm
>
>
> $arr1 = array(1,2,2,3,1,2,0,4,5,2);
>
> $groups = [];
> $group = [];
> $prev = NULL;
> foreach ($arr1 as $value) {
> if ($group && $prev > $value) {
> $groups[] = $group;
> $group = [];
> }
> $group[] = $value;
> $prev = $value;
> }
> if ($group) {
> $groups[] = $group;
> }
>
> print_r($groups);
>
>
> If needed, the comparison function can be separated out and passed as
> a parameter.
> So the array_group() function with a comparison callback parameter can
> be implemented in userland.
>
> I think you need to make a case as to why the behavior you describe
> justifies a native function.
> E.g. if you find a lot of public php code that does this kind of grouping.
>
> I personally suspect it is not that common.
>
> Cheers
> Andreas
>
>
> On Tue, 30 May 2023 at 17:08, Boro Sitnikovski <buritomath@gmail.com> wrote:
> >
> > Hey,
> >
> > Thanks for the suggestion.
> >
> > For the previous case in the code, I added these in a Gist to not clutter here too much:
> >
> > 1. The first example corresponds to %Y¥ØªI\Fóž“
> > Vhttps://gist.github.com/bor0/b5f449bfe85440d96abd933b9f03b310#file-test_manual_group-php
> > 2. The second example corresponds to
> > https://gist.github.com/bor0/b5f449bfe85440d96abd933b9f03b310#file-test_array_group-php
> > 3. Another example, addressing the problem of increasing subsequences is very simple with
> >
array_group:
> > https://gist.github.com/bor0/b5f449bfe85440d96abd933b9f03b310#file-test_array_incr_subseqs-php
> >
> > Best,
> >
> > Boro
> >
> > > On 30.5.2023, at 16:57, Andreas Hennings <andreas@dqxtech.net> wrote:
> > >
> > > Hello Boro,
> > > I think you should include the "expected result" in your code examples.
> > > Maybe this is in your patch file, but I don't think we want to look at
> > > that for discussion.
> > >
> > > Cheers
> > > Andreas
> > >
> > > On Tue, 30 May 2023 at 13:35, Boro Sitnikovski <buritomath@gmail.com> wrote:
> > >>
> > >> Hello all,
> > >>
> > >> As per the How To Create an RFC instructions, I am sending this e-mail in order
> > >> to get your feedback on my proposal.
> > >>
> > >> I propose introducing a function to PHP core named
> > >> array_group. This function takes an array and a function and returns
> > >> an array that contains arrays - groups of consecutive elements. This is very similar to
> > >> Haskell's groupBy function.
> > >>
> > >> For some background as to why - usually, when people want to do grouping in PHP,
> > >> they use hash maps, so something like:
> > >>
> > >> ```
> > >> <?php
> > >> $array = [
> > >> [ 'id' => 1, 'value' => 'foo' ],
> > >> [ 'id' => 1, 'value' => 'bar' ],
> > >> [ 'id' => 2, 'value' => 'baz' ],
> > >> ];
> > >>
> > >> $groups = [];
> > >> foreach ( $array as $element ) {
> > >> $groups[ $element['id'] ][] = $element;
> > >> }
> > >>
> > >> var_dump( $groups );
> > >> ```
> > >>
> > >> This can now be achieved as follows (not preserving keys):
> > >>
> > >> ```
> > >> <?php
> > >> $array = [
> > >> [ 'id' => 1, 'value' => 'foo' ],
> > >> [ 'id' => 1, 'value' => 'bar' ],
> > >> [ 'id' => 2, 'value' => 'baz' ],
> > >> ];
> > >>
> > >> $groups = array_group( $array, function( $a, $b ) {
> > >> return $a['id'] == $b['id'];
> > >> } );
> > >> ```
> > >>
> > >> The disadvantage of the first approach is that we are only limited to using
> > >> equality check, and we cannot group by, say, < or other
> > >> functions.
> > >> Similarly, the advantage of the first approach is that the keys are preserved,
> > >> and elements needn't be consecutive.
> > >>
> > >> In any case, I think a utility function such as
> > >> array_group will be widely useful.
> > >>
> > >> Please find attached a patch with a proposed implementation. Curious about your
> > >> feedback.
> > >>
> > >> Best,
> > >>
> > >> Boro Sitnikovski
> > >>
> >