diff --git a/src/Illuminate/Collections/Collection.php b/src/Illuminate/Collections/Collection.php index c3fdf3e273ee..686ec06a3bdd 100644 --- a/src/Illuminate/Collections/Collection.php +++ b/src/Illuminate/Collections/Collection.php @@ -1070,6 +1070,34 @@ 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; + } + + + $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..bc2ac873325c 100644 --- a/src/Illuminate/Collections/LazyCollection.php +++ b/src/Illuminate/Collections/LazyCollection.php @@ -1082,6 +1082,36 @@ 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..151351c51794 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 */