diff --git a/docs/pages/api.rst b/docs/pages/api.rst index 1343e1a24..5eb06e18e 100644 --- a/docs/pages/api.rst +++ b/docs/pages/api.rst @@ -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 ~~~~~~~~~ @@ -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 diff --git a/spec/loophp/collection/CollectionSpec.php b/spec/loophp/collection/CollectionSpec.php index be3782e2e..1b14cce9b 100644 --- a/spec/loophp/collection/CollectionSpec.php +++ b/spec/loophp/collection/CollectionSpec.php @@ -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')) diff --git a/src/Collection.php b/src/Collection.php index a44084ddc..36f3b20ae 100644 --- a/src/Collection.php +++ b/src/Collection.php @@ -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; @@ -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)); diff --git a/src/Contract/Collection.php b/src/Contract/Collection.php index a66d83b83..b8f59047f 100644 --- a/src/Contract/Collection.php +++ b/src/Contract/Collection.php @@ -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; @@ -117,6 +118,7 @@ * @template-extends Groupable * @template-extends Hasable * @template-extends Headable + * @template-extends IfThenElseable * @template-extends Intersectable * @template-extends Intersectkeysable * @template-extends Intersperseable @@ -190,6 +192,7 @@ interface Collection extends Groupable, Hasable, Headable, + IfThenElseable, Implodeable, Intersectable, Intersectkeysable, diff --git a/src/Contract/Operation/IfThenElseable.php b/src/Contract/Operation/IfThenElseable.php new file mode 100644 index 000000000..2a98c35a0 --- /dev/null +++ b/src/Contract/Operation/IfThenElseable.php @@ -0,0 +1,20 @@ + + */ + public function ifThenElse(callable $condition, callable $then, ?callable $else = null): Collection; +} diff --git a/src/Operation/IfThenElse.php b/src/Operation/IfThenElse.php new file mode 100644 index 000000000..fbce20e58 --- /dev/null +++ b/src/Operation/IfThenElse.php @@ -0,0 +1,48 @@ +storage = [ + 'condition' => $condition, + 'then' => $then, + 'else' => $else, + ]; + } + + // phpcs:disable + /** + * @psalm-return Closure(Iterator, callable(T, TKey): bool, callable(T, TKey): (T|TKey), callable(T, TKey): (T|TKey)): Generator + */ + // 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); + } + }; + } +}