diff --git a/spec/drupol/collection/CollectionSpec.php b/spec/drupol/collection/CollectionSpec.php index d417d6e07..6b535ae57 100644 --- a/spec/drupol/collection/CollectionSpec.php +++ b/spec/drupol/collection/CollectionSpec.php @@ -490,6 +490,58 @@ public function it_can_get_the_last_item(): void ->shouldReturn(null); } + public function it_can_intersperse(): void + { + $this + ->beConstructedThrough('with', [\range('A', 'F')]); + + $this + ->intersperse('foo', 2, 0) + ->shouldIterateAs([ + 0 => 'foo', + 1 => 'A', + 2 => 'B', + 3 => 'foo', + 4 => 'C', + 5 => 'D', + 6 => 'foo', + 7 => 'E', + 8 => 'F', + ]); + + $this + ->intersperse('foo', 2, 1) + ->shouldIterateAs([ + 0 => 'A', + 1 => 'foo', + 2 => 'B', + 3 => 'C', + 4 => 'foo', + 5 => 'D', + 6 => 'E', + 7 => 'foo', + 8 => 'F', + ]); + + $this + ->intersperse('foo', 2, 2) + ->shouldIterateAs([ + 0 => 'foo', + 1 => 'A', + 2 => 'B', + 3 => 'foo', + 4 => 'C', + 5 => 'D', + 6 => 'foo', + 7 => 'E', + 8 => 'F', + ]); + + $this + ->shouldThrow(\Exception::class) + ->during('intersperse', ['foo', -1, 1]); + } + public function it_can_keys(): void { $this diff --git a/src/Collection.php b/src/Collection.php index 24336ec72..9a661a035 100644 --- a/src/Collection.php +++ b/src/Collection.php @@ -22,6 +22,7 @@ use drupol\collection\Operation\Flip; use drupol\collection\Operation\Forget; use drupol\collection\Operation\Get; +use drupol\collection\Operation\Intersperse; use drupol\collection\Operation\Keys; use drupol\collection\Operation\Last; use drupol\collection\Operation\Limit; @@ -182,6 +183,14 @@ public function getIterator() return $this->makeIterator($this->source); } + /** + * {@inheritdoc} + */ + public function intersperse($element, int $every = 1, int $startAt = 0): CollectionInterface + { + return $this->run(Intersperse::with($element, $every, $startAt)); + } + /** * {@inheritdoc} */ diff --git a/src/Contract/Collection.php b/src/Contract/Collection.php index 2b97781f1..627b2cfd7 100644 --- a/src/Contract/Collection.php +++ b/src/Contract/Collection.php @@ -135,6 +135,18 @@ public function get($key, $default = null); */ public function getIterator(); + /** + * Insert a given value between each element of a collection. + * Indices are not preserved. + * + * @param mixed $element + * @param int $every + * @param int $startAt + * + * @return \drupol\collection\Contract\Collection + */ + public function intersperse($element, int $every = 1, int $startAt = 0): self; + /** * Get the keys of the items. * diff --git a/src/Operation/Intersperse.php b/src/Operation/Intersperse.php new file mode 100644 index 000000000..cd5f5ee65 --- /dev/null +++ b/src/Operation/Intersperse.php @@ -0,0 +1,44 @@ +parameters; + + if (0 >= $every) { + throw new \InvalidArgumentException('The parameter must be greater than zero.'); + } + + return Collection::with( + static function () use ($element, $every, $startAt, $collection): \Generator { + $i = $startAt; + + foreach ($collection as $key => $value) { + if (0 === $i % $every) { + yield $element; + } + + yield $value; + ++$i; + } + } + ); + } +}