Skip to content

Commit

Permalink
feat: Add Coalesce operation.
Browse files Browse the repository at this point in the history
  • Loading branch information
drupol committed Apr 20, 2021
1 parent 1425343 commit 6e5c758
Show file tree
Hide file tree
Showing 8 changed files with 178 additions and 1 deletion.
31 changes: 30 additions & 1 deletion docs/pages/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,26 @@ Signature: ``Collection::chunk(int $size);``
$collection->chunk(2);
coalesce
~~~~~~~~

Return the first *non-nullsy* value in a collection.

*Nullsy* values are:

* The null value: null
* Empty array: []
* The integer zero: 0
* The boolean: false
* The empty string: ''

Interface: `Coalesceable`_

Signature: ``Collection::coalesce();``

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

collapse
~~~~~~~~

Expand Down Expand Up @@ -1179,7 +1199,15 @@ Signature: ``Collection::nth(int $step, int $offset = 0);``
nullsy
~~~~~~

Check if the collection contains nullsy values.
Check if the collection contains *nullsy* values.

*Nullsy* values are:

* The null value: `null`
* Empty array: `[]`
* The integer zero: `0`
* The boolean: `false`
* The empty string: `''`

Interface: `Nullsyable`_

Expand Down Expand Up @@ -2143,6 +2171,7 @@ Signature: ``Collection::zip(iterable ...$iterables);``
.. _Combinateable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Combinateable.php
.. _Combineable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Combineable.php
.. _Compactable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Compactable.php
.. _Coalesceable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Coalesceable.php
.. _Containsable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Containsable.php
.. _Currentable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Currentable.php
.. _Cycleable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Cycleable.php
Expand Down
19 changes: 19 additions & 0 deletions docs/pages/code/operations/coalesce.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace App;

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

use loophp\collection\Collection;

$input = range('a', 'e');

$collection = Collection::fromIterable($input)
->coalesce(); // [ 0 => 'a' ]

$input = ['', null, 'foo', false, ...range('a', 'e')];

$collection = Collection::fromIterable($input)
->coalesce(); // [ 2 => 'foo' ]
19 changes: 19 additions & 0 deletions spec/loophp/collection/CollectionSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,25 @@ public function it_can_chunk(): void
->shouldIterateAs([[0 => 'A', 1 => 'B'], [0 => 'C', 1 => 'D', 2 => 'E'], [0 => 'F']]);
}

public function it_can_coalesce(): void
{
$input = range('a', 'e');

$this::fromIterable($input)
->coalesce()
->shouldIterateAs([
0 => 'a',
]);

$input = ['', null, 'foo', false, ...range('a', 'e')];

$this::fromIterable($input)
->coalesce()
->shouldIterateAs([
2 => 'foo',
]);
}

public function it_can_collapse(): void
{
$generator = static function () {
Expand Down
48 changes: 48 additions & 0 deletions spec/loophp/collection/Operation/CoalesceSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

declare(strict_types=1);

namespace spec\loophp\collection\Operation;

use ArrayIterator;
use loophp\collection\Operation\Coalesce;
use PhpSpec\ObjectBehavior;

class CoalesceSpec extends ObjectBehavior
{
public function it_can_coalesce()
{
$input = range('a', 'e');

$iterator = new ArrayIterator($input);

$this
->__invoke()($iterator)
->shouldHaveCount(1);

$this
->__invoke()($iterator)
->shouldIterateAs([
0 => 'a',
]);

$input = ['', null, 'foo', false, ...range('a', 'e')];

$iterator = new ArrayIterator($input);

$this
->__invoke()($iterator)
->shouldHaveCount(1);

$this
->__invoke()($iterator)
->shouldIterateAs([
2 => 'foo',
]);
}

public function it_is_initializable()
{
$this->shouldHaveType(Coalesce::class);
}
}
6 changes: 6 additions & 0 deletions src/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use loophp\collection\Operation\AsyncMap;
use loophp\collection\Operation\Cache;
use loophp\collection\Operation\Chunk;
use loophp\collection\Operation\Coalesce;
use loophp\collection\Operation\Collapse;
use loophp\collection\Operation\Column;
use loophp\collection\Operation\Combinate;
Expand Down Expand Up @@ -201,6 +202,11 @@ public function chunk(int ...$sizes): CollectionInterface
return new self(Chunk::of()(...$sizes), $this->getIterator());
}

public function coalesce(): CollectionInterface
{
return new self(Coalesce::of(), $this->getIterator());
}

public function collapse(): CollectionInterface
{
return new self(Collapse::of(), $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 @@ -15,6 +15,7 @@
use loophp\collection\Contract\Operation\AsyncMapable;
use loophp\collection\Contract\Operation\Cacheable;
use loophp\collection\Contract\Operation\Chunkable;
use loophp\collection\Contract\Operation\Coalesceable;
use loophp\collection\Contract\Operation\Collapseable;
use loophp\collection\Contract\Operation\Columnable;
use loophp\collection\Contract\Operation\Combinateable;
Expand Down Expand Up @@ -123,6 +124,7 @@
* @template-extends AsyncMapable<TKey, T>
* @template-extends Cacheable<TKey, T>
* @template-extends Chunkable<TKey, T>
* @template-extends Coalesceable<TKey, T>
* @template-extends Collapseable<TKey, T>
* @template-extends Columnable<TKey, T>
* @template-extends Combinateable<TKey, T>
Expand Down Expand Up @@ -224,6 +226,7 @@ interface Collection extends
AsyncMapable,
Cacheable,
Chunkable,
Coalesceable,
Collapseable,
Columnable,
Combinateable,
Expand Down
22 changes: 22 additions & 0 deletions src/Contract/Operation/Coalesceable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?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 Coalesceable
{
/**
* Return the first non-nullsy value of the collection.
*
* @psalm-return \loophp\collection\Collection<TKey, T>
*/
public function coalesce(): Collection;
}
31 changes: 31 additions & 0 deletions src/Operation/Coalesce.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace loophp\collection\Operation;

use Closure;
use Generator;

/**
* @psalm-template TKey
* @psalm-template TKey of array-key
* @psalm-template T
*/
final class Coalesce extends AbstractOperation
{
/**
* @psalm-return Closure(Iterator<TKey, T>): Generator<TKey, T>
*/
public function __invoke(): Closure
{
/** @psalm-var Closure(Iterator<TKey, T>): Generator<TKey, T> $pipe */
$pipe = Pipe::of()(
Compact::of()(),
Head::of(),
);

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

0 comments on commit 6e5c758

Please sign in to comment.