Skip to content

Commit

Permalink
feat: Add match operation.
Browse files Browse the repository at this point in the history
  • Loading branch information
drupol committed Dec 26, 2020
1 parent b08ee64 commit fa01f65
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 2 deletions.
23 changes: 23 additions & 0 deletions docs/pages/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1056,6 +1056,28 @@ Signature: ``Collection::map(callable ...$callbacks);``
$collection = Collection::fromIterable(range(1, 100))
->map($mapper);
match
~~~~~

Check if the collection has a value that match a callback.

The returned value is true if the callback match at least one element
of the collection. False otherwise.

Interface: `Matchable`_

Signature: ``Collection::match(callable $callback);``

.. code-block:: php
$matcher = static function(int $value): bool {
return $value % 2;
};
$collection = Collection::fromIterable(range(1, 100))
->match($matcher)
->current(); // true
merge
~~~~~

Expand Down Expand Up @@ -2049,6 +2071,7 @@ Signature: ``Collection::zip(iterable ...$iterables);``
.. _Limitable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Limitable.php
.. _Linesable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Linesable.php
.. _Mapable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Mapable.php
.. _Matchable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Matchable.php
.. _Mergeable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Mergeable.php
.. _Normalizeable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Normalizeable.php
.. _Nthable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Nthable.php
Expand Down
25 changes: 23 additions & 2 deletions spec/loophp/collection/CollectionSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -1229,15 +1229,15 @@ static function ($key, $value) {

$this::fromIterable(['b', 1, 'foo', 'bar'])
->has(
static function ($key, $value) {
static function ($value, $key) {
return 'foo';
}
)
->shouldIterateAs([2 => true]);

$this::fromIterable(['b', 1, 'foo', 'bar'])
->has(
static function ($key, $value) {
static function ($value, $key) {
return 'unknown';
}
)
Expand Down Expand Up @@ -1575,6 +1575,27 @@ public function it_can_map(): void
]);
}

public function it_can_match(): void
{
$input = range(1, 10);

$this::fromIterable($input)
->match(
static function (int $value): bool {
return 7 === $value;
}
)
->shouldIterateAs([6 => true]);

$this::fromIterable($input)
->match(
static function (int $value): bool {
return 17 === $value;
}
)
->shouldIterateAs([0 => false]);
}

public function it_can_merge(): void
{
$collection = Collection::fromCallable(static function () {
Expand Down
6 changes: 6 additions & 0 deletions src/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
use loophp\collection\Operation\Limit;
use loophp\collection\Operation\Lines;
use loophp\collection\Operation\Map;
use loophp\collection\Operation\Match;
use loophp\collection\Operation\Merge;
use loophp\collection\Operation\Normalize;
use loophp\collection\Operation\Nth;
Expand Down Expand Up @@ -531,6 +532,11 @@ public function map(callable ...$callbacks): CollectionInterface
return new self(Map::of()(...$callbacks), $this->getIterator());
}

public function match(callable $callback): CollectionInterface
{
return new self(Match::of()(static fn () => true)($callback), $this->getIterator());
}

public function merge(iterable ...$sources): CollectionInterface
{
return new self(Merge::of()(...$sources), $this->getIterator());
Expand Down
3 changes: 3 additions & 0 deletions src/Contract/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
use loophp\collection\Contract\Operation\Limitable;
use loophp\collection\Contract\Operation\Linesable;
use loophp\collection\Contract\Operation\Mapable;
use loophp\collection\Contract\Operation\Matchable;
use loophp\collection\Contract\Operation\Mergeable;
use loophp\collection\Contract\Operation\Normalizeable;
use loophp\collection\Contract\Operation\Nthable;
Expand Down Expand Up @@ -164,6 +165,7 @@
* @template-extends Limitable<TKey, T>
* @template-extends Linesable<TKey, T>
* @template-extends Mapable<TKey, T>
* @template-extends Matchable<TKey, T>
* @template-extends Mergeable<TKey, T>
* @template-extends Normalizeable<TKey, T>
* @template-extends Nthable<TKey, T>
Expand Down Expand Up @@ -265,6 +267,7 @@ interface Collection extends
Limitable,
Linesable,
Mapable,
Matchable,
Mergeable,
Normalizeable,
Nthable,
Expand Down
23 changes: 23 additions & 0 deletions src/Contract/Operation/Matchable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace loophp\collection\Contract\Operation;

use Iterator;
use loophp\collection\Contract\Collection;

/**
* @psalm-template TKey
* @psalm-template TKey of array-key
* @psalm-template T
*/
interface Matchable
{
/**
* @psalm-param callable(T, TKey, Iterator<TKey, T>): bool $callback
*
* @psalm-return \loophp\collection\Collection<int, bool>
*/
public function match(callable $callback): Collection;
}
71 changes: 71 additions & 0 deletions src/Operation/Match.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

declare(strict_types=1);

namespace loophp\collection\Operation;

use Closure;
use Generator;
use Iterator;

/**
* @psalm-template TKey
* @psalm-template TKey of array-key
* @psalm-template T
*
* phpcs:disable Generic.Files.LineLength.TooLong
*/
final class Match extends AbstractOperation
{
/**
* @psalm-return Closure(callable(T, TKey, Iterator<TKey, T>): T): Closure(callable(T, TKey, Iterator<TKey, T>): T): Closure(Iterator<TKey, T>): Generator<int, bool>
*/
public function __invoke(): Closure
{
return
/**
* @psalm-param callable(T, TKey, Iterator<TKey, T>): T $matcher
*
* @psalm-return Closure(callable(T, TKey, Iterator<TKey, T>): T): Closure(Iterator<TKey, T>): Generator<int, bool>
*/
static function (callable $matcher): Closure {
return
/**
* @psalm-param callable(T, TKey, Iterator<TKey, T>): T $callback
*
* @psalm-return Closure(Iterator<TKey, T>): Generator<int, bool>
*/
static function (callable $callback) use ($matcher): Closure {
$mapCallback =
/**
* @param mixed $value
* @psalm-param T $value
*
* @param mixed $key
* @psalm-param TKey $key
*
* @psalm-param Iterator<TKey, T> $iterator
*/
static fn ($value, $key, Iterator $iterator): bool => $matcher($value, $key, $iterator) === $callback($value, $key, $iterator);

$dropWhileCallback =
/**
* @param mixed $value
* @psalm-param T $value
*/
static fn ($value): bool => !(bool) $value;

/** @psalm-var Closure(Iterator<TKey, T>): Generator<int, bool> $pipe */
$pipe = Pipe::of()(
Map::of()($mapCallback),
DropWhile::of()($dropWhileCallback),
Append::of()(false),
Head::of()
);

// Point free style.
return $pipe;
};
};
}
}

0 comments on commit fa01f65

Please sign in to comment.