From 54eac0856b51e0ab601355e06292fadac9f48745 Mon Sep 17 00:00:00 2001 From: Joseph Silber Date: Wed, 21 Aug 2019 00:15:43 -0400 Subject: [PATCH] Add `chunkStartingWith` and `chunkEndingWith` collection methods --- src/Illuminate/Support/Collection.php | 28 ++++++++++ src/Illuminate/Support/Enumerable.php | 18 ++++++ src/Illuminate/Support/LazyCollection.php | 56 +++++++++++++++++++ tests/Support/SupportCollectionTest.php | 34 +++++++++++ .../SupportLazyCollectionIsLazyTest.php | 30 ++++++++++ 5 files changed, 166 insertions(+) diff --git a/src/Illuminate/Support/Collection.php b/src/Illuminate/Support/Collection.php index 686a9697e466..c3fd523ff912 100644 --- a/src/Illuminate/Support/Collection.php +++ b/src/Illuminate/Support/Collection.php @@ -1033,6 +1033,34 @@ public function chunk($size) return new static($chunks); } + /** + * Chunk the collection into chunks that + * start with an item passing the given test. + * + * @param callable $callback + * @return static + */ + public function chunkStartingWith(callable $callback) + { + return new static( + $this->lazy()->chunkStartingWith($callback)->mapInto(static::class) + ); + } + + /** + * Chunk the collection into chunks that + * end with an item passing the given test. + * + * @param callable $callback + * @return static + */ + public function chunkEndingWith(callable $callback) + { + return new static( + $this->lazy()->chunkEndingWith($callback)->mapInto(static::class) + ); + } + /** * Sort through each item with a callback. * diff --git a/src/Illuminate/Support/Enumerable.php b/src/Illuminate/Support/Enumerable.php index bee901145379..4b6fc46fcb70 100644 --- a/src/Illuminate/Support/Enumerable.php +++ b/src/Illuminate/Support/Enumerable.php @@ -800,6 +800,24 @@ public function split($numberOfGroups); */ public function chunk($size); + /** + * Chunk the collection into chunks that + * start with an item passing the given test. + * + * @param callable $callback + * @return static + */ + public function chunkStartingWith(callable $callback); + + /** + * Chunk the collection into chunks that + * end with an item passing the given test. + * + * @param callable $callback + * @return static + */ + public function chunkEndingWith(callable $callback); + /** * Sort through each item with a callback. * diff --git a/src/Illuminate/Support/LazyCollection.php b/src/Illuminate/Support/LazyCollection.php index 08961251a3c7..e97b4a7c2f6f 100644 --- a/src/Illuminate/Support/LazyCollection.php +++ b/src/Illuminate/Support/LazyCollection.php @@ -1130,6 +1130,62 @@ public function chunk($size) }); } + /** + * Chunk the collection into chunks that + * start with an item passing the given test. + * + * @param callable $callback + * @return static + */ + public function chunkStartingWith(callable $callback) + { + return new static(function () use ($callback) { + $chunk = []; + + foreach ($this as $key => $value) { + if ($callback($value, $key) && ! empty($chunk)) { + yield new static($chunk); + + $chunk = []; + } + + $chunk[$key] = $value; + } + + if (! empty($chunk)) { + yield new static($chunk); + } + }); + } + + /** + * Chunk the collection into chunks that + * end with an item passing the given test. + * + * @param callable $callback + * @return static + */ + public function chunkEndingWith(callable $callback) + { + return new static(function () use ($callback) { + $chunk = []; + + foreach ($this as $key => $value) { + $chunk[$key] = $value; + + if ($callback($value, $key) && ! empty($chunk)) { + yield new static($chunk); + + $chunk = []; + } + } + + if (! empty($chunk)) { + yield new static($chunk); + } + }); + } + /** * Sort through each item with a callback. * diff --git a/tests/Support/SupportCollectionTest.php b/tests/Support/SupportCollectionTest.php index 689715937428..fa648289ded0 100755 --- a/tests/Support/SupportCollectionTest.php +++ b/tests/Support/SupportCollectionTest.php @@ -1514,6 +1514,40 @@ public function testChunkWhenGivenLessThanZero($collection) ); } + /** + * @dataProvider collectionClassProvider + */ + public function testChunkStartingWith($collection) + { + $data = new $collection( + ['header', 1, 2, 'header', 1, 'header', 'header'] + ); + + $this->assertEquals( + [['header', 1, 2], ['header', 1], ['header'], ['header']], + $data->chunkStartingWith(function ($value, $key) { + return $value == 'header'; + })->map->values()->toArray() + ); + } + + /** + * @dataProvider collectionClassProvider + */ + public function testChunkEndingWith($collection) + { + $data = new $collection( + ['footer', 1, 2, 'footer', 1, 'footer', 1, 2] + ); + + $this->assertEquals( + [['footer'], [1, 2, 'footer'], [1, 'footer'], [1, 2]], + $data->chunkEndingWith(function ($value, $key) { + return $value == 'footer'; + })->map->values()->toArray() + ); + } + /** * @dataProvider collectionClassProvider */ diff --git a/tests/Support/SupportLazyCollectionIsLazyTest.php b/tests/Support/SupportLazyCollectionIsLazyTest.php index 0936cbc51c16..e08f5d34f61d 100644 --- a/tests/Support/SupportLazyCollectionIsLazyTest.php +++ b/tests/Support/SupportLazyCollectionIsLazyTest.php @@ -30,6 +30,36 @@ public function testChunkIsLazy() }); } + public function testChunkEndingWithIsLazy() + { + $this->assertDoesNotEnumerate(function ($collection) { + $collection->chunkEndingWith(function ($value) { + return $value % 5 == 0; + }); + }); + + $this->assertEnumerates(15, function ($collection) { + $collection->chunkEndingWith(function ($value) { + return $value % 5 == 0; + })->take(3)->all(); + }); + } + + public function testChunkStartingWithIsLazy() + { + $this->assertDoesNotEnumerate(function ($collection) { + $collection->chunkStartingWith(function ($value) { + return $value % 5 == 0; + }); + }); + + $this->assertEnumerates(15, function ($collection) { + $collection->chunkStartingWith(function ($value) { + return $value % 5 == 0; + })->take(3)->all(); + }); + } + public function testCollapseIsLazy() { $collection = LazyCollection::make([