Skip to content

Commit

Permalink
Update Filter operation.
Browse files Browse the repository at this point in the history
BREAKING CHANGE: yes
  • Loading branch information
drupol committed Jul 6, 2021
1 parent 5edb9e7 commit 330bb4f
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 23 deletions.
22 changes: 9 additions & 13 deletions docs/pages/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -717,22 +717,18 @@ Signature: ``Collection::falsy();``
filter
~~~~~~

Filter collection items based on one or more callbacks. Multiple callbacks will be treated as a logical ``AND``.
Filter collection items based on one or more callbacks.

.. warning:: The `callbacks` parameter is variadic and will be evaluated as a logical ``OR``.
If you're looking for a logical ``AND``, you have to make multiple calls to the
same operation.

Interface: `Filterable`_

Signature: ``Collection::filter(callable ...$callbacks);``

.. code-block:: php
$divisibleBy3 = static fn($value): bool => 0 === $value % 3;
$divisibleBy6 = static fn($value): bool => 0 === $value % 6;
$collection = Collection::fromIterable(range(1, 10))
->filter($divisibleBy3); // [3, 6, 9]
$collection = Collection::fromIterable(range(1, 10))
->filter($divisibleBy3, $divisibleBy6); // [6]
.. literalinclude:: code/operations/filter.php
:language: php

first
~~~~~
Expand Down Expand Up @@ -773,13 +769,13 @@ Signature: ``Collection::flatMap(callable $callback);``

.. code-block:: php
$square = static fn (int $val): int => $val ** 2;
$square = static fn (int $val): int => $val ** 2;
$squareArray = static fn (int $val): array => [$val ** 2];
$squareCollection = static fn (int $val): Collection => Collection::fromIterable([$val ** 2]);
$collection = Collection::fromIterable(range(1, 3))
->flatMap($squareArray); // [1, 4, 9]
$collection = Collection::fromIterable(range(1, 3))
->flatMap($squareCollection); // [1, 4, 9]
Expand Down
23 changes: 23 additions & 0 deletions docs/pages/code/operations/filter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?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;

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

use loophp\collection\Collection;

$divisibleBy3 = static fn($value): bool => 0 === $value % 3;
$divisibleBy5 = static fn($value): bool => 0 === $value % 5;

$collection = Collection::fromIterable(range(1, 10))
->filter($divisibleBy3); // [3, 6, 9]

$collection = Collection::fromIterable(range(1, 10))
->filter($divisibleBy3, $divisibleBy5); // [3, 5, 6, 0, 10]
52 changes: 42 additions & 10 deletions src/Operation/Filter.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

namespace loophp\collection\Operation;

use CallbackFilterIterator;
use Closure;
use Generator;
use Iterator;

/**
Expand All @@ -26,23 +26,49 @@ final class Filter extends AbstractOperation
/**
* @pure
*
* @return Closure(callable(T , TKey, Iterator<TKey, T>): bool ...): Closure (Iterator<TKey, T>): Iterator<TKey, T>
* @return Closure(callable(T , TKey, Iterator<TKey, T>): bool ...): Closure (Iterator<TKey, T>): Generator<TKey, T>
*/
public function __invoke(): Closure
{
return
/**
* @param callable(T, TKey, Iterator<TKey, T>): bool ...$callbacks
*
* @return Closure(Iterator<TKey, T>): Iterator<TKey, T>
* @return Closure(Iterator<TKey, T>): Generator<TKey, T>
*/
static fn (callable ...$callbacks): Closure =>
/**
* @param Iterator<TKey, T> $iterator
*
* @return Iterator<TKey, T>
* @return Generator<TKey, T>
*/
static function (Iterator $iterator) use ($callbacks): Iterator {
static function (Iterator $iterator) use ($callbacks): Generator {
// TODO: Find a way to avoid repeating this everywhere.
$reducerCallback =
/**
* @param TKey $key
*
* @return Closure(T): Closure(Iterator<TKey, T>): Closure(bool, callable(T, TKey, Iterator<TKey, T>): bool): bool
*/
static fn ($key): Closure =>
/**
* @param T $current
*
* @return Closure(Iterator<TKey, T>): Closure(bool, callable(T, TKey, Iterator<TKey, T>): bool): bool
*/
static fn ($current): Closure =>
/**
* @param Iterator<TKey, T> $iterator
*
* @return Closure(bool, callable(T, TKey, Iterator<TKey, T>): bool): bool
*/
static fn (Iterator $iterator): Closure =>
/**
* @param bool $carry
* @param callable(T, TKey, Iterator<TKey, T>): bool $callable
*/
static fn (bool $carry, callable $callable): bool => $carry || $callable($current, $key, $iterator);

$defaultCallback =
/**
* @param T $value
Expand All @@ -53,11 +79,17 @@ static function (Iterator $iterator) use ($callbacks): Iterator {
[$defaultCallback] :
$callbacks;

return array_reduce(
$callbacks,
static fn (Iterator $carry, callable $callback): CallbackFilterIterator => new CallbackFilterIterator($carry, $callback),
$iterator
);
foreach ($iterator as $key => $current) {
$result = array_reduce(
$callbacks,
$reducerCallback($key)($current)($iterator),
false
);

if ($result) {
yield $key => $current;
}
}
};
}
}

0 comments on commit 330bb4f

Please sign in to comment.