Re: [RFC] [Discussion] Add new function `array_group`
| From: | Boro Sitnikovski | Date: | Wed, 31 May 2023 00:09:36 +0000 |
| Subject: | Re: [RFC] [Discussion] Add new function `array_group` | ||
| References: | 1 2 3 4 5 6 7 8 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-120481@lists.php.net to get a copy of this message | ||
> On 30.5.2023, at 21:56, Andreas Hennings <andreas@dqxtech.net> wrote:
>
> On Tue, 30 May 2023 at 19:25, Boro Sitnikovski <buritomath@gmail.com> wrote:
>>
>> Here's some more examples:
>>
>> 1. Use
array_group to create list of singleton list:
>> ```
>> $groups = array_group( $arr, function( $p1, $p2 ) {
>> return false;
>> } );
>> ```
>>
>> (This can also be achieved with array_map returning
>> [ $x ])
>>
>> 2. Distinct groups for consecutive positive and negative elements
>>
>> ```
>> $arr = [-1,2,-3,-4,2,1,2,-3,1,1,2];
>>
>> $groups = array_group( $arr, function( $p1, $p2 ) {
>> return ($p1 > 0) == ($p2 > 0);
>> } );
>> ```
>>
>> This produces [[-1],[2],[-3,-4],[2,1,2],[-3],[1,1,2]], so
>> we can easily capture the groups of highs/lows for example.
>>
>> 3. Group sentences (similar to explode, but still
>> different)
>>
>> ```
>> $arr = "Hello, PHP. Good to see you.";
>> $groups = array_group( str_split( $arr ), function( $p1, $p2 ) {
>> return '.' !== $p1;
>> } );
>>
>> $groups = array_map( 'join', $groups );
>> ```
>>
>> Producing [ "Hello, PHP.", " Good to see you."
>> ].
>>
>> 4. Grouping book sections
>> ```
>> $book_sections = [ '1.0', '1.1', '1.2', '2.0',
>> '2.1', '3.0', '3.1' ];
>> $groups = array_group( $book_sections, function( $p1, $p2 ) {
>> return $p1[0] === $p2[0];
>> } );
>> ```
>>
>> Producing [ [ '1.0', '1.1', '1.2' ], [
>> '2.0', '2.1'], [ '3.0', '3.1' ] ]
>>
>> and so on...
>>
>> Basically, it's a very general utility :)
>>
>> Best,
>>
>> Boro
>
> Only one of these examples actually uses a comparison function that
> actually compares two adjacent values.
> All the others look at a single value only, or they don't care about
> the original order at all.
>
> And that example (2) seems quite artificial and rare.
>
>> so we can easily capture the groups of highs/lows for example
>
> How often does this problem come up in practice?
>
> I did actually have a look at the Haskell doc page you linked.
>
> https://hackage.haskell.org/package/groupBy-0.1.0.0/docs/Data-List-GroupBy..htmlÜÁØa.îÍV
> zè<€9
> I wonder where this is used in the Haskell world, and how often they
> need this true comparison of adjacent values.
> The examples from the doc page are quite artificial. That's ok for a
> doc page, but does not make a good argument for why we need it.
Thanks for digging deeper in trying to understand the value that this would bring.
For a more realistic example, check the following gist: https://gist.github.com/bor0/b5f449bfe85440d96abd933b9f03b310#file-test_datetime_group-php.
This was a very recent thing I worked on in production. The events came ordered from the database.
But also, this is not the first time I was in need of a grouping functionality.
Sorry for repeating, but I see it as a handy utility. We can bring the same argument for any of the
array_* functions because most of them can be implemented with for loops.
If the main concern is the consecutive processing of the elements, we could add a third argument to
array_group (flag) that would allow users to alter the processing behaviour - at a
price, consecutive taking O(n) vs all elements taking something close to O(n^2)