Skip to content

Commit

Permalink
Add IfThenElse operation.
Browse files Browse the repository at this point in the history
  • Loading branch information
drupol committed Aug 27, 2020
1 parent f5ceeb8 commit f9c0c04
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 0 deletions.
32 changes: 32 additions & 0 deletions docs/pages/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,37 @@ Signature: ``Collection::head();``
Collection::fromIterable($generator())
->head(); // [1 => 'a']
ifThenElse
~~~~~~~~~~

Execute a callback when a condition is met.

Interface: `IfThenElseable`_

Signature: ``Collection::ifThenElse(callable $condition, callable $then, ?callable $else = null);``

.. code-block:: php
$input = range(1, 5);
$condition = static function (int $value): bool {
return 0 === $value % 2;
};
$then = static function (int $value): int {
return $value * $value;
};
$else = static function (int $value): int {
return $value + 2;
};
Collection::fromIterable($input)
->ifThenElse($condition, $then); // [1, 4, 3, 16, 5]
Collection::fromIterable($input)
->ifThenElse($condition, $then, $else) // [3, 4, 5, 16, 7]
intersect
~~~~~~~~~

Expand Down Expand Up @@ -1516,6 +1547,7 @@ Interface: `Truthyable`_
.. _Groupable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Groupable.php
.. _Hasable: https://github.com/loophp/collection/blob/master/src/Contract/Transformation/Hasable.php
.. _Headable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Headable.php
.. _IfThenElseable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/IfThenElseable.php
.. _Implodeable: https://github.com/loophp/collection/blob/master/src/Contract/Transformation/Implodeable.php
.. _Intersectable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Intersectable.php
.. _Intersectkeysable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Intersectkeysable.php
Expand Down
29 changes: 29 additions & 0 deletions spec/loophp/collection/CollectionSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -1043,6 +1043,35 @@ public function it_can_head(): void
->shouldIterateAs([0 => 'A']);
}

public function it_can_if_then_else()
{
$input = range(1, 5);

$condition = static function ($value) {
return 0 === $value % 2;
};

$then = static function ($value) {
return $value * $value;
};

$else = static function ($value) {
return $value + 2;
};

$this::fromIterable($input)
->ifThenElse($condition, $then)
->shouldIterateAs([
1, 4, 3, 16, 5,
]);

$this::fromIterable($input)
->ifThenElse($condition, $then, $else)
->shouldIterateAs([
3, 4, 5, 16, 7,
]);
}

public function it_can_implode(): void
{
$this::fromIterable(range('A', 'C'))
Expand Down
10 changes: 10 additions & 0 deletions src/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
use loophp\collection\Operation\Frequency;
use loophp\collection\Operation\Group;
use loophp\collection\Operation\Head;
use loophp\collection\Operation\IfThenElse;
use loophp\collection\Operation\Intersect;
use loophp\collection\Operation\IntersectKeys;
use loophp\collection\Operation\Intersperse;
Expand Down Expand Up @@ -432,6 +433,15 @@ public function head(): CollectionInterface
return $this->run(new Head());
}

public function ifThenElse(callable $condition, callable $then, ?callable $else = null): CollectionInterface
{
$else = $else ?? static function ($value, $key) {
return $value;
};

return $this->run(new IfThenElse($condition, $then, $else));
}

public function implode(string $glue = ''): string
{
return $this->transform(new Implode($glue));
Expand Down
3 changes: 3 additions & 0 deletions src/Contract/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
use loophp\collection\Contract\Operation\Frequencyable;
use loophp\collection\Contract\Operation\Groupable;
use loophp\collection\Contract\Operation\Headable;
use loophp\collection\Contract\Operation\IfThenElseable;
use loophp\collection\Contract\Operation\Intersectable;
use loophp\collection\Contract\Operation\Intersectkeysable;
use loophp\collection\Contract\Operation\Intersperseable;
Expand Down Expand Up @@ -117,6 +118,7 @@
* @template-extends Groupable<TKey, T>
* @template-extends Hasable<TKey, T>
* @template-extends Headable<TKey, T>
* @template-extends IfThenElseable<TKey, T>
* @template-extends Intersectable<TKey, T>
* @template-extends Intersectkeysable<TKey, T>
* @template-extends Intersperseable<TKey, T>
Expand Down Expand Up @@ -190,6 +192,7 @@ interface Collection extends
Groupable,
Hasable,
Headable,
IfThenElseable,
Implodeable,
Intersectable,
Intersectkeysable,
Expand Down
20 changes: 20 additions & 0 deletions src/Contract/Operation/IfThenElseable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace loophp\collection\Contract\Operation;

use loophp\collection\Contract\Collection;

/**
* @psalm-template TKey
* @psalm-template TKey of array-key
* @psalm-template T
*/
interface IfThenElseable
{
/**
* @psalm-return \loophp\collection\Contract\Collection<TKey, T>
*/
public function ifThenElse(callable $condition, callable $then, ?callable $else = null): Collection;
}
48 changes: 48 additions & 0 deletions src/Operation/IfThenElse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

declare(strict_types=1);

namespace loophp\collection\Operation;

use Closure;
use Generator;
use Iterator;
use loophp\collection\Contract\Operation;

/**
* @psalm-template TKey
* @psalm-template TKey of array-key
* @psalm-template T
*/
final class IfThenElse extends AbstractOperation implements Operation
{
/**
* @psalm-param callable(T, TKey): bool $condition
* @psalm-param callable(T, TKey): (T|TKey) $then
* @psalm-param callable(T, TKey): (T|TKey) $else
*/
public function __construct(callable $condition, callable $then, callable $else)
{
$this->storage = [
'condition' => $condition,
'then' => $then,
'else' => $else,
];
}

// phpcs:disable
/**
* @psalm-return Closure(Iterator<TKey, T>, callable(T, TKey): bool, callable(T, TKey): (T|TKey), callable(T, TKey): (T|TKey)): Generator<TKey, T>
*/
// phpcs:enable
public function __invoke(): Closure
{
return static function (Iterator $iterator, callable $condition, callable $then, callable $else): Generator {
foreach ($iterator as $key => $value) {
yield $key => $condition($value, $key) ?
$then($value, $key) :
$else($value, $key);
}
};
}
}

0 comments on commit f9c0c04

Please sign in to comment.