Skip to content

Commit

Permalink
Add reductions operation
Browse files Browse the repository at this point in the history
  • Loading branch information
paulbalandan committed Dec 11, 2024
1 parent c8cc6a6 commit b255ac6
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 0 deletions.
21 changes: 21 additions & 0 deletions src/Nexus/Collection/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,27 @@ public function partition(\Closure $predicate): self
}, [$this]);
}

/**
* @template TAcc
*
* @return self<int, TAcc>
*/
public function reductions(\Closure $predicate, mixed $initial = null): self
{
return new self(
static function (iterable $collection) use ($predicate, $initial): iterable {
$accumulator = $initial;

foreach ($collection as $key => $item) {
$accumulator = $predicate($accumulator, $item, $key);

yield $accumulator;
}
},
[$this],
);
}

/**
* @return self<TKey, T>
*/
Expand Down
2 changes: 2 additions & 0 deletions src/Nexus/Collection/CollectionInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
* @extends Operation\MapKeys<TKey, T>
* @extends Operation\MapWithKey<TKey, T>
* @extends Operation\Partition<TKey, T>
* @extends Operation\Reductions<TKey, T>
* @extends Operation\Reject<TKey, T>
* @extends Operation\Slice<TKey, T>
* @extends Operation\Take<TKey, T>
Expand Down Expand Up @@ -65,6 +66,7 @@ interface CollectionInterface extends
Operation\MapKeys,
Operation\MapWithKey,
Operation\Partition,
Operation\Reductions,
Operation\Reject,
Operation\Slice,
Operation\Take,
Expand Down
41 changes: 41 additions & 0 deletions src/Nexus/Collection/Operation/Reductions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

/**
* This file is part of the Nexus framework.
*
* (c) John Paul E. Balandan, CPA <paulbalandan@gmail.com>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace Nexus\Collection\Operation;

use Nexus\Collection\CollectionInterface;

/**
* @template TKey
* @template T
*/
interface Reductions
{
/**
* Returns a new collection consisting of the intermediate values
* of reducing the collection using a `$predicate`.
*
* The reduction `$predicate` is passed an `$initial` accumulator
* and the current collection value and returns a new accumulator.
*
* Reductions returns a list of every accumulator along the way.
*
* @template TAcc
*
* @param (\Closure(TAcc, T, TKey): TAcc) $predicate
* @param TAcc $initial
*
* @return CollectionInterface<int, TAcc>
*/
public function reductions(\Closure $predicate, mixed $initial = null): CollectionInterface;
}
10 changes: 10 additions & 0 deletions tests/Collection/AbstractCollectionTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,16 @@ public function testPartition(): void
self::assertSame([2 => 'banana', 3 => 'cherry', 4 => 'date'], $collection->all()[1]->all(true));
}

public function testReduction(): void
{
self::assertSame(
[1, 4, 9, 16, 25],
$this->collection()
->reductions(static fn(int $acc, int $v, int $k): int => $acc + $v + $k, 0)
->all(),
);
}

public function testReject(): void
{
$predicate = static fn(int $item, string $key): bool => str_starts_with($key, 'd') && $item > 2;
Expand Down

0 comments on commit b255ac6

Please sign in to comment.