From cf816a3d6c861520accfe7cec443229b3e2c8148 Mon Sep 17 00:00:00 2001 From: Pol Dellaiera Date: Mon, 7 Sep 2020 17:30:02 +0200 Subject: [PATCH] Add DropWhile operation. --- docs/pages/api.rst | 20 +++++++++ spec/loophp/collection/CollectionSpec.php | 22 ++++++++++ src/Collection.php | 6 +++ src/Contract/Collection.php | 3 ++ src/Contract/Operation/DropWhileable.php | 20 +++++++++ src/Operation/DropWhile.php | 53 +++++++++++++++++++++++ 6 files changed, 124 insertions(+) create mode 100644 src/Contract/Operation/DropWhileable.php create mode 100644 src/Operation/DropWhile.php diff --git a/docs/pages/api.rst b/docs/pages/api.rst index 3d701bb73..c89aa2dbc 100644 --- a/docs/pages/api.rst +++ b/docs/pages/api.rst @@ -463,6 +463,25 @@ Signature: ``Collection::distinct();`` $collection = Collection::with(['a', 'b', 'c', 'd', 'a']) ->distinct() +dropWhile +~~~~~~~~~ + +It inspects the original collection and takes from it its elements from the moment when the condition fails for the +first time till the end of the list. + +Interface: `DropWhileable`_ + +Signature: ``Collection::dropWhile(callable $callback);`` + +.. code-block:: php + + $isSmallerThanThree = static function (int $value): bool { + return 3 > $value; + }; + + Collection::fromIterable([1,2,3,4,5,6,7,8,9,1,2,3]) + ->dropWhile($isSmallerThanThree); // [3,4,5,6,7,8,9,1,2,3] + explode ~~~~~~~ @@ -1558,6 +1577,7 @@ Signature: ``Collection::zip(iterable ...$iterables);`` .. _Diffable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Diffable.php .. _Diffkeysable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Diffkeysable.php .. _Distinctable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Distinctable.php +.. _DropWhileable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/DropWhileable.php .. _Explodeable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Explodeable.php .. _Falsyable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Falsyable.php .. _Filterable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Filterable.php diff --git a/spec/loophp/collection/CollectionSpec.php b/spec/loophp/collection/CollectionSpec.php index b5663dff3..d9b784c04 100644 --- a/spec/loophp/collection/CollectionSpec.php +++ b/spec/loophp/collection/CollectionSpec.php @@ -543,6 +543,28 @@ public function it_can_do_the_cartesian_product(): void ->shouldIterateAs([0 => ['A', 1], 1 => ['A', 2], 2 => ['B', 1], 3 => ['B', 2], 4 => ['C', 1], 5 => ['C', 2]]); } + public function it_can_dropWhile(): void + { + $isSmallerThanThree = static function ($value) { + return 3 > $value; + }; + + $this::fromIterable([1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3]) + ->dropWhile($isSmallerThanThree) + ->shouldIterateAs([ + 2 => 3, + 3 => 4, + 4 => 5, + 5 => 6, + 6 => 7, + 7 => 8, + 8 => 9, + 9 => 1, + 10 => 2, + 11 => 3, + ]); + } + public function it_can_explode(): void { $string = 'I am just a random piece of text.'; diff --git a/src/Collection.php b/src/Collection.php index 253a293fc..b461e33a5 100644 --- a/src/Collection.php +++ b/src/Collection.php @@ -29,6 +29,7 @@ use loophp\collection\Operation\Diff; use loophp\collection\Operation\DiffKeys; use loophp\collection\Operation\Distinct; +use loophp\collection\Operation\DropWhile; use loophp\collection\Operation\Explode; use loophp\collection\Operation\Falsy; use loophp\collection\Operation\Filter; @@ -324,6 +325,11 @@ public function distinct(): CollectionInterface return $this->run(Distinct::of()); } + public function dropWhile(callable $callback): CollectionInterface + { + return $this->run(DropWhile::of()($callback)); + } + public static function empty(): Collection { return new self(); diff --git a/src/Contract/Collection.php b/src/Contract/Collection.php index 5023c5d0a..3df5bfca2 100644 --- a/src/Contract/Collection.php +++ b/src/Contract/Collection.php @@ -23,6 +23,7 @@ use loophp\collection\Contract\Operation\Diffable; use loophp\collection\Contract\Operation\Diffkeysable; use loophp\collection\Contract\Operation\Distinctable; +use loophp\collection\Contract\Operation\DropWhileable; use loophp\collection\Contract\Operation\Explodeable; use loophp\collection\Contract\Operation\Falsyable; use loophp\collection\Contract\Operation\Filterable; @@ -109,6 +110,7 @@ * @template-extends Diffable * @template-extends Diffkeysable * @template-extends Distinctable + * @template-extends DropWhileable * @template-extends Explodeable * @template-extends Filterable * @template-extends Firstable @@ -185,6 +187,7 @@ interface Collection extends Diffable, Diffkeysable, Distinctable, + DropWhileable, Explodeable, Falsyable, Filterable, diff --git a/src/Contract/Operation/DropWhileable.php b/src/Contract/Operation/DropWhileable.php new file mode 100644 index 000000000..78abd0a37 --- /dev/null +++ b/src/Contract/Operation/DropWhileable.php @@ -0,0 +1,20 @@ + + */ + public function dropWhile(callable $callback): Collection; +} diff --git a/src/Operation/DropWhile.php b/src/Operation/DropWhile.php new file mode 100644 index 000000000..0d29a42c4 --- /dev/null +++ b/src/Operation/DropWhile.php @@ -0,0 +1,53 @@ +): bool)): Closure(Iterator): Generator + */ + public function __invoke(): Closure + { + return + /** + * @psalm-param callable(T, TKey, Iterator):bool $callback + * + * @psalm-return Closure(Iterator): Generator + */ + static function (callable $callback): Closure { + return + /** + * @psalm-param Iterator $iterator + * + * @psalm-return Generator + */ + static function (Iterator $iterator) use ($callback): Generator { + for (; $iterator->valid(); $iterator->next()) { + if (true === $callback($iterator->current(), $iterator->key(), $iterator)) { + continue; + } + + break; + } + + for (; $iterator->valid(); $iterator->next()) { + yield $iterator->key() => $iterator->current(); + } + }; + }; + } +}