diff --git a/docs/en/index.rst b/docs/en/index.rst index 251e9503..7d35850d 100644 --- a/docs/en/index.rst +++ b/docs/en/index.rst @@ -229,6 +229,18 @@ Applies the given function to each element in the collection and returns a new c return $value + 1; }); // [2, 3, 4] +reduce +------ + +Applies iteratively the given function to each element in the collection, so as to reduce the collection to a single value. + +.. code-block:: php + $collection = new ArrayCollection([1, 2, 3]); + + $reduce = $collection->reduce(function(int $accumulator, int $value): int { + return $accumulator + $value; + }, 0); // 6 + next ---- diff --git a/lib/Doctrine/Common/Collections/AbstractLazyCollection.php b/lib/Doctrine/Common/Collections/AbstractLazyCollection.php index dae801cc..03c48dff 100644 --- a/lib/Doctrine/Common/Collections/AbstractLazyCollection.php +++ b/lib/Doctrine/Common/Collections/AbstractLazyCollection.php @@ -244,6 +244,16 @@ public function map(Closure $func): Collection return $this->collection->map($func); } + /** + * {@inheritDoc} + */ + public function reduce(Closure $func, $initial = null) + { + $this->initialize(); + + return $this->collection->reduce($func, $initial); + } + /** * {@inheritDoc} */ diff --git a/lib/Doctrine/Common/Collections/ArrayCollection.php b/lib/Doctrine/Common/Collections/ArrayCollection.php index f507e296..1049291b 100644 --- a/lib/Doctrine/Common/Collections/ArrayCollection.php +++ b/lib/Doctrine/Common/Collections/ArrayCollection.php @@ -13,6 +13,7 @@ use function array_key_exists; use function array_keys; use function array_map; +use function array_reduce; use function array_reverse; use function array_search; use function array_slice; @@ -349,6 +350,14 @@ public function map(Closure $func): Collection return $this->createFrom(array_map($func, $this->elements)); } + /** + * {@inheritDoc} + */ + public function reduce(Closure $func, $initial = null) + { + return array_reduce($this->elements, $func, $initial); + } + /** * {@inheritDoc} * diff --git a/lib/Doctrine/Common/Collections/Collection.php b/lib/Doctrine/Common/Collections/Collection.php index c0a5e2cf..1390402e 100644 --- a/lib/Doctrine/Common/Collections/Collection.php +++ b/lib/Doctrine/Common/Collections/Collection.php @@ -261,6 +261,22 @@ public function forAll(Closure $p): bool; */ public function map(Closure $func): self; + /** + * Applies iteratively the given function to each element in the collection, + * so as to reduce the collection to a single value. + * + * @param mixed $initial + * + * @return mixed + * + * @psalm-template TReturn + * @psalm-template TInitial + * @psalm-param Closure(TReturn|TInitial, T):TReturn $func + * @psalm-param TInitial|null $initial + * @psalm-return TReturn|TInitial|null + */ + public function reduce(Closure $func, $initial = null); + /** * Partitions this collection in two collections according to a predicate. * Keys are preserved in the resulting collections. diff --git a/tests/Doctrine/Tests/Common/Collections/BaseCollectionTest.php b/tests/Doctrine/Tests/Common/Collections/BaseCollectionTest.php index 63e02211..1eef01ab 100644 --- a/tests/Doctrine/Tests/Common/Collections/BaseCollectionTest.php +++ b/tests/Doctrine/Tests/Common/Collections/BaseCollectionTest.php @@ -76,6 +76,19 @@ public function testMap(): void self::assertEquals([2, 4], $res->toArray()); } + public function testReduce(): void + { + $this->collection->add(1); + $this->collection->add(2); + $this->collection->add(3); + $this->collection->add(4); + + $res = $this->collection->reduce(static function ($sum, $e) { + return $sum + $e; + }); + self::assertSame(10, $res); + } + public function testFilter(): void { $this->collection->add(1);