From 934b22619cac62272dcb09ab435524aa7a518035 Mon Sep 17 00:00:00 2001 From: redgluten Date: Sun, 23 Aug 2020 21:08:51 +0200 Subject: [PATCH 1/4] Add `chunkWhile()` collection method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is inspired by the similar method in [Ruby’s Enumerable](https://ruby-doc.org/core-2.7.1/Enumerable.html#method-i-chunk_while). --- src/Illuminate/Collections/Collection.php | 26 ++++++++++++++ src/Illuminate/Collections/Enumerable.php | 8 +++++ src/Illuminate/Collections/LazyCollection.php | 27 ++++++++++++++ tests/Support/SupportCollectionTest.php | 36 +++++++++++++++++++ 4 files changed, 97 insertions(+) diff --git a/src/Illuminate/Collections/Collection.php b/src/Illuminate/Collections/Collection.php index c3fdf3e273ee..7ba8c5655eef 100644 --- a/src/Illuminate/Collections/Collection.php +++ b/src/Illuminate/Collections/Collection.php @@ -1070,6 +1070,32 @@ public function chunk($size) return new static($chunks); } + /** + * Chunk the collection into chunks with a callback. + * + * @param callable $callback + * @return static + */ + public function chunkWhile(callable $callback) + { + $chunks = []; + + $chunk = []; + foreach ($this->items as $current) { + if (isset($previous) && !$callback($previous, $current)) { + $chunks[] = new static($chunk); + $chunk = []; + } + + $chunk[] = $current; + $previous = $current; + } + // Add the last chunk before closing. + $chunks[] = new static($chunk); + + return new static($chunks); + } + /** * Sort through each item with a callback. * diff --git a/src/Illuminate/Collections/Enumerable.php b/src/Illuminate/Collections/Enumerable.php index 5c512e46dc9d..a2c8c8eea042 100644 --- a/src/Illuminate/Collections/Enumerable.php +++ b/src/Illuminate/Collections/Enumerable.php @@ -752,6 +752,14 @@ public function split($numberOfGroups); */ public function chunk($size); + /** + * Chunk the collection into chunks with a callback. + * + * @param callable $callback + * @return static + */ + public function chunkWhile(callable $callback); + /** * Sort through each item with a callback. * diff --git a/src/Illuminate/Collections/LazyCollection.php b/src/Illuminate/Collections/LazyCollection.php index 4dfc3b2ae7fe..fdf1fd73c79e 100644 --- a/src/Illuminate/Collections/LazyCollection.php +++ b/src/Illuminate/Collections/LazyCollection.php @@ -1082,6 +1082,33 @@ public function chunk($size) }); } + /** + * Chunk the collection into chunks with a callback. + * + * @param callable $callback + * @return static + */ + public function chunkWhile(callable $callback) + { + return new static(function () use ($callback) { + $iterator = $this->getIterator(); + + $chunk = []; + while ($iterator->valid()) { + if (isset($previous) && !$callback($previous, $iterator->current())) { + yield new static($chunk); + $chunk = []; + } + + $chunk[] = $iterator->current(); + $previous = $iterator->current(); + + $iterator->next(); + } + yield new static($chunk); + }); + } + /** * Sort through each item with a callback. * diff --git a/tests/Support/SupportCollectionTest.php b/tests/Support/SupportCollectionTest.php index 9640a3a541a4..a6cef7c39927 100755 --- a/tests/Support/SupportCollectionTest.php +++ b/tests/Support/SupportCollectionTest.php @@ -1643,6 +1643,42 @@ public function testChunkWhenGivenLessThanZero($collection) ); } + /** + * @dataProvider collectionClassProvider + */ + public function testChunkWhileOnEqualElements($collection) + { + $data = (new $collection(['A', 'A', 'B', 'B', 'C', 'C', 'C'])) + ->chunkWhile(function ($previous, $current) { + return $previous === $current; + }); + + $this->assertInstanceOf($collection, $data); + $this->assertInstanceOf($collection, $data->first()); + $this->assertEquals(['A', 'A'], $data->first()->toArray()); + $this->assertEquals(['B','B'], $data->get(1)->toArray()); + $this->assertEquals(['C', 'C', 'C'], $data->last()->toArray()); + } + + /** + * @dataProvider collectionClassProvider + */ + public function testChunkWhileOnContiguouslyIncreasingIntegers($collection) + { + $data = (new $collection([1, 4, 9, 10, 11, 12, 15, 16, 19, 20, 21])) + ->chunkWhile(function ($previous, $current) { + return $previous + 1 == $current; + }); + + $this->assertInstanceOf($collection, $data); + $this->assertInstanceOf($collection, $data->first()); + $this->assertEquals([1], $data->first()->toArray()); + $this->assertEquals([4], $data->get(1)->toArray()); + $this->assertEquals([9, 10, 11, 12], $data->get(2)->toArray()); + $this->assertEquals([15, 16], $data->get(3)->toArray()); + $this->assertEquals([19, 20, 21], $data->last()->toArray()); + } + /** * @dataProvider collectionClassProvider */ From 0f465071f5fcb8a62b44045bc8898643a524de81 Mon Sep 17 00:00:00 2001 From: redgluten Date: Sun, 23 Aug 2020 22:36:49 +0200 Subject: [PATCH 2/4] chunkWhile: fix style code issues --- src/Illuminate/Collections/Collection.php | 2 +- src/Illuminate/Collections/LazyCollection.php | 2 +- tests/Support/SupportCollectionTest.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Illuminate/Collections/Collection.php b/src/Illuminate/Collections/Collection.php index 7ba8c5655eef..be1420f910e0 100644 --- a/src/Illuminate/Collections/Collection.php +++ b/src/Illuminate/Collections/Collection.php @@ -1082,7 +1082,7 @@ public function chunkWhile(callable $callback) $chunk = []; foreach ($this->items as $current) { - if (isset($previous) && !$callback($previous, $current)) { + if (isset($previous) && ! $callback($previous, $current)) { $chunks[] = new static($chunk); $chunk = []; } diff --git a/src/Illuminate/Collections/LazyCollection.php b/src/Illuminate/Collections/LazyCollection.php index fdf1fd73c79e..3d6f955b35d9 100644 --- a/src/Illuminate/Collections/LazyCollection.php +++ b/src/Illuminate/Collections/LazyCollection.php @@ -1095,7 +1095,7 @@ public function chunkWhile(callable $callback) $chunk = []; while ($iterator->valid()) { - if (isset($previous) && !$callback($previous, $iterator->current())) { + if (isset($previous) && ! $callback($previous, $iterator->current())) { yield new static($chunk); $chunk = []; } diff --git a/tests/Support/SupportCollectionTest.php b/tests/Support/SupportCollectionTest.php index a6cef7c39927..151351c51794 100755 --- a/tests/Support/SupportCollectionTest.php +++ b/tests/Support/SupportCollectionTest.php @@ -1656,7 +1656,7 @@ public function testChunkWhileOnEqualElements($collection) $this->assertInstanceOf($collection, $data); $this->assertInstanceOf($collection, $data->first()); $this->assertEquals(['A', 'A'], $data->first()->toArray()); - $this->assertEquals(['B','B'], $data->get(1)->toArray()); + $this->assertEquals(['B', 'B'], $data->get(1)->toArray()); $this->assertEquals(['C', 'C', 'C'], $data->last()->toArray()); } From f7a4a969396c32bceac403a24152259af01adfa3 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Mon, 24 Aug 2020 08:23:51 -0500 Subject: [PATCH 3/4] Update Collection.php --- src/Illuminate/Collections/Collection.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Illuminate/Collections/Collection.php b/src/Illuminate/Collections/Collection.php index be1420f910e0..686ec06a3bdd 100644 --- a/src/Illuminate/Collections/Collection.php +++ b/src/Illuminate/Collections/Collection.php @@ -1081,6 +1081,7 @@ public function chunkWhile(callable $callback) $chunks = []; $chunk = []; + foreach ($this->items as $current) { if (isset($previous) && ! $callback($previous, $current)) { $chunks[] = new static($chunk); @@ -1090,7 +1091,8 @@ public function chunkWhile(callable $callback) $chunk[] = $current; $previous = $current; } - // Add the last chunk before closing. + + $chunks[] = new static($chunk); return new static($chunks); From bf93bf2671e32d2c056e529d552fb5bde292e5e8 Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Mon, 24 Aug 2020 08:24:31 -0500 Subject: [PATCH 4/4] Update LazyCollection.php --- src/Illuminate/Collections/LazyCollection.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Illuminate/Collections/LazyCollection.php b/src/Illuminate/Collections/LazyCollection.php index 3d6f955b35d9..bc2ac873325c 100644 --- a/src/Illuminate/Collections/LazyCollection.php +++ b/src/Illuminate/Collections/LazyCollection.php @@ -1094,9 +1094,11 @@ public function chunkWhile(callable $callback) $iterator = $this->getIterator(); $chunk = []; + while ($iterator->valid()) { if (isset($previous) && ! $callback($previous, $iterator->current())) { yield new static($chunk); + $chunk = []; } @@ -1105,6 +1107,7 @@ public function chunkWhile(callable $callback) $iterator->next(); } + yield new static($chunk); }); }