Skip to content

Commit

Permalink
feat: Add Group operation.
Browse files Browse the repository at this point in the history
  • Loading branch information
drupol committed Oct 7, 2020
1 parent 248e5a4 commit a7df56c
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 0 deletions.
16 changes: 16 additions & 0 deletions docs/pages/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,21 @@ get

Interface: `Getable`_

group
~~~~~

Takes a list and returns a list of lists such that the concatenation of the result is equal to the argument.
Moreover, each sublist in the result contains only equal elements.

Interface: `Groupable`_

Signature: ``Collection::group();``

.. code-block:: php
Collection::fromString('Mississippi')
->group(); // [ [0 => 'M'], [1 => 'i'], [2 => 's', 3 => 's'], [4 => 'i'], [5 => 's', 6 => 's'], [7 => 'i'], [8 => 'p', 9 => 'p'], [10 => 'i'] ]
groupBy
~~~~~~~

Expand Down Expand Up @@ -1965,6 +1980,7 @@ Signature: ``Collection::zip(iterable ...$iterables);``
.. _Forgetable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Forgetable.php
.. _Frequencyable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Frequencyable.php
.. _Getable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Getable.php
.. _Groupable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Groupable.php
.. _GroupByable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/GroupByable.php
.. _Hasable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Hasable.php
.. _Headable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Headable.php
Expand Down
16 changes: 16 additions & 0 deletions spec/loophp/collection/CollectionSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -976,6 +976,22 @@ public function it_can_get_the_last_item(): void
]);
}

public function it_can_group(): void
{
$this::fromString('Mississippi')
->group()
->shouldIterateAs([
0 => [0 => 'M'],
1 => [1 => 'i'],
2 => [2 => 's', 3 => 's'],
4 => [4 => 'i'],
5 => [5 => 's', 6 => 's'],
7 => [7 => 'i'],
8 => [8 => 'p', 9 => 'p'],
10 => [10 => 'i'],
]);
}

public function it_can_groupBy(): void
{
$callback = static function () {
Expand Down
6 changes: 6 additions & 0 deletions src/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
use loophp\collection\Operation\Forget;
use loophp\collection\Operation\Frequency;
use loophp\collection\Operation\Get;
use loophp\collection\Operation\Group;
use loophp\collection\Operation\GroupBy;
use loophp\collection\Operation\Has;
use loophp\collection\Operation\Head;
Expand Down Expand Up @@ -508,6 +509,11 @@ public function getIterator(): ClosureIterator
return new ClosureIterator($this->source, ...$this->parameters);
}

public function group(): CollectionInterface
{
return $this->run(Group::of());
}

public function groupBy(?callable $callable = null): CollectionInterface
{
return $this->run(GroupBy::of()($callable));
Expand Down
3 changes: 3 additions & 0 deletions src/Contract/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
use loophp\collection\Contract\Operation\Forgetable;
use loophp\collection\Contract\Operation\Frequencyable;
use loophp\collection\Contract\Operation\Getable;
use loophp\collection\Contract\Operation\Groupable;
use loophp\collection\Contract\Operation\GroupByable;
use loophp\collection\Contract\Operation\Hasable;
use loophp\collection\Contract\Operation\Headable;
Expand Down Expand Up @@ -143,6 +144,7 @@
* @template-extends Forgetable<TKey, T>
* @template-extends Frequencyable<TKey, T>
* @template-extends Getable<TKey, T>
* @template-extends Groupable<TKey, T>
* @template-extends GroupByable<TKey, T>
* @template-extends Hasable<TKey, T>
* @template-extends Headable<TKey, T>
Expand Down Expand Up @@ -237,6 +239,7 @@ interface Collection extends
Forgetable,
Frequencyable,
Getable,
Groupable,
GroupByable,
Hasable,
Headable,
Expand Down
20 changes: 20 additions & 0 deletions src/Contract/Operation/Groupable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace loophp\collection\Contract\Operation;

use loophp\collection\Contract\Collection;

/**
* @psalm-template TKey
* @psalm-template TKey of array-key
* @psalm-template T
*/
interface Groupable
{
/**
* @psalm-return \loophp\collection\Contract\Collection<TKey, T>
*/
public function group(): Collection;
}
63 changes: 63 additions & 0 deletions src/Operation/Group.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

declare(strict_types=1);

namespace loophp\collection\Operation;

use Closure;
use Generator;
use Iterator;

/**
* @psalm-template TKey
* @psalm-template TKey of array-key
* @psalm-template T
*
* phpcs:disable Generic.WhiteSpace.ScopeIndent.IncorrectExact
*/
final class Group extends AbstractOperation
{
/**
* @psalm-return Closure(Iterator<TKey, T>): Generator<int, list<T>>
*/
public function __invoke(): Closure
{
return
/**
* @psalm-param Iterator<TKey, T> $iterator
*
* @psalm-return Generator<int, list<T>>
*/
static function (Iterator $iterator): Generator {
$spanCallback =
/**
* @psalm-param T $current
*
* @psalm-return Closure(T): bool
*
* @param mixed $current
*/
static function ($current): Closure {
return
/**
* @psalm-param T $value
*
* @param mixed $value
*/
static function ($value) use ($current): bool {
return $value === $current;
};
};

for (; $iterator->valid(); $span->next(), $iterator = $span->current()) {
$key = $iterator->key();
$current = $iterator->current();

/** @psalm-var Iterator<int, Iterator<TKey, T>> $span */
$span = Span::of()($spanCallback($current))($iterator);

yield $key => iterator_to_array($span->current());
}
};
}
}

0 comments on commit a7df56c

Please sign in to comment.