Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add Averages operation. #238

Merged
merged 2 commits into from
Mar 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions docs/pages/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,25 @@ Signature: ``Collection::asyncMapN(callable ...$callbacks): Collection;``
$collection = Collection::fromIterable(['c' => 3, 'b' => 2, 'a' => 1])
->asyncMapN($mapper1, $mapper2); // ['a' => 2, 'b' => 4, 'c' => 6]

averages
~~~~~~~~

Calculate the average of a collection of numbers.

The average constitute the result obtained by adding together several amounts
and then dividing this total by the number of amounts.

Based on `scanLeft1`, this operation will return the average at each iteration.
Therefore, if you're looking for one single result, you must get the last item
using `last` operation.

Interface: `Averagesable`_

Signature: ``Collection::averages(): Collection;``

.. literalinclude:: code/operations/averages.php
:language: php

cache
~~~~~

Expand Down Expand Up @@ -2486,6 +2505,7 @@ Signature: ``Collection::zip(iterable ...$iterables): Collection;``
.. _Associateable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Associateable.php
.. _AsyncMapable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/AsyncMapable.php
.. _AsyncMapNable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/AsyncMapNable.php
.. _Averagesable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Averagesable.php
.. _Cacheable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Cacheable.php
.. _Chunkable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Chunkable.php
.. _Collapseable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Collapseable.php
Expand Down
24 changes: 24 additions & 0 deletions docs/pages/code/operations/averages.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

/**
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

declare(strict_types=1);

namespace App;

use loophp\collection\Collection;

include __DIR__ . '/../../../../vendor/autoload.php';

$collection = Collection::fromIterable([1, 2, 3, 4, 5])
->averages(); // [1, 1.5, 2, 2.5, 3] from [1/1, (1+2)/2, (1+2+3)/3 ...]

$average = Collection::fromIterable([1, 2, 3, 4, 5])
->averages()
->last(); // [3]

$collection = Collection::empty()
->averages(); // []
8 changes: 7 additions & 1 deletion psalm-baseline.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="4.20.0@f82a70e7edfc6cf2705e9374c8a0b6a974a779ed">
<files psalm-version="4.22.0@fc2c6ab4d5fa5d644d8617089f012f3bb84b8703">
<file src="src/Collection.php">
<InvalidArgument occurrences="5">
<code>$callback</code>
Expand Down Expand Up @@ -37,4 +37,10 @@
<code>Closure(bool): Closure(iterable&lt;TKey, T&gt;): (Generator&lt;int, T&gt;|Generator&lt;TKey, T&gt;)</code>
</InvalidReturnType>
</file>
<file src="src/Operation/Averages.php">
<InvalidReturnStatement occurrences="1"/>
<InvalidReturnType occurrences="1">
<code>Closure(iterable&lt;TKey, T&gt;): Generator&lt;int, float&gt;</code>
</InvalidReturnType>
</file>
</files>
6 changes: 6 additions & 0 deletions src/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use loophp\collection\Operation\Associate;
use loophp\collection\Operation\AsyncMap;
use loophp\collection\Operation\AsyncMapN;
use loophp\collection\Operation\Averages;
use loophp\collection\Operation\Cache;
use loophp\collection\Operation\Chunk;
use loophp\collection\Operation\Coalesce;
Expand Down Expand Up @@ -209,6 +210,11 @@ public function asyncMapN(callable ...$callbacks): CollectionInterface
return new self((new AsyncMapN())()(...$callbacks), [$this]);
}

public function averages(): CollectionInterface
{
return new self((new Averages())(), [$this]);
}

public function cache(?CacheItemPoolInterface $cache = null): CollectionInterface
{
return new self((new Cache())()($cache ?? new ArrayAdapter()), [$this]);
Expand Down
3 changes: 3 additions & 0 deletions src/Contract/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use loophp\collection\Contract\Operation\Associateable;
use loophp\collection\Contract\Operation\AsyncMapable;
use loophp\collection\Contract\Operation\AsyncMapNable;
use loophp\collection\Contract\Operation\Averagesable;
use loophp\collection\Contract\Operation\Cacheable;
use loophp\collection\Contract\Operation\Chunkable;
use loophp\collection\Contract\Operation\Coalesceable;
Expand Down Expand Up @@ -142,6 +143,7 @@
* @template-extends Associateable<TKey, T>
* @template-extends AsyncMapable<TKey, T>
* @template-extends AsyncMapNable<TKey, T>
* @template-extends Averagesable<TKey, T>
* @template-extends Cacheable<TKey, T>
* @template-extends Chunkable<TKey, T>
* @template-extends Coalesceable<TKey, T>
Expand Down Expand Up @@ -259,6 +261,7 @@ interface Collection extends
Associateable,
AsyncMapable,
AsyncMapNable,
Averagesable,
Cacheable,
Chunkable,
Coalesceable,
Expand Down
36 changes: 36 additions & 0 deletions src/Contract/Operation/Averagesable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

/**
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

declare(strict_types=1);

namespace loophp\collection\Contract\Operation;

use loophp\collection\Contract\Collection;

/**
* @template TKey
* @template T
*/
interface Averagesable
{
/**
* Calculate the average of a collection of numbers.
*
* The average constitute the result obtained by adding together several
* amounts and then dividing this total by the number of amounts.
*
* Based on `scanLeft1`, this operation will return the average at each
* iteration.
* Therefore, if you're looking for one single result, you must get the last
* item using `last` operation.
*
* @see https://loophp-collection.readthedocs.io/en/stable/pages/api.html#averages
*
* @return Collection<int, float>
*/
public function averages(): Collection;
}
37 changes: 37 additions & 0 deletions src/Operation/Averages.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

/**
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

declare(strict_types=1);

namespace loophp\collection\Operation;

use Closure;
use Generator;

/**
* @immutable
*
* @template TKey
* @template T
*
* phpcs:disable Generic.Files.LineLength.TooLong
*/
final class Averages extends AbstractOperation
{
/**
* @return Closure(iterable<TKey, T>): Generator<int, float>
*/
public function __invoke(): Closure
{
return (new Pipe())()(
(new Normalize())(),
(new ScanLeft1())()(
static fn (float $acc, float $value, int $key): float => ($acc * $key + $value) / ($key + 1)
)
);
}
}
1 change: 1 addition & 0 deletions tests/unit/CollectionGenericOperationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ final class CollectionGenericOperationTest extends TestCase
* @dataProvider associateOperationProvider
* @dataProvider asyncMapOperationProvider
* @dataProvider asyncMapNOperationProvider
* @dataProvider averagesOperationProvider
* @dataProvider cacheOperationProvider
* @dataProvider chunkOperationProvider
* @dataProvider coalesceOperationProvider
Expand Down
20 changes: 20 additions & 0 deletions tests/unit/Traits/GenericCollectionProviders.php
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,26 @@ static function (int $v): int {
];
}

public function averagesOperationProvider()
{
$operation = 'averages';
$input = array_combine(range('a', 'f'), range(0, 5));

yield [
$operation,
[],
$input,
[(int) 0, (float) .5, (float) 1.0, (float) 1.5, (float) 2.0, (float) 2.5],
];

yield [
$operation,
[],
[],
[],
];
}

public function cacheOperationProvider()
{
$operation = 'cache';
Expand Down