Skip to content

Commit

Permalink
Update First operation.
Browse files Browse the repository at this point in the history
  • Loading branch information
drupol committed Aug 22, 2020
1 parent 1d15657 commit c7ac8b3
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 104 deletions.
47 changes: 41 additions & 6 deletions docs/pages/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,46 @@ Signature: ``Collection::filter(callable ...$callbacks);``
$collection = Collection::with(range(1, 100))
->filter($callback);
first
~~~~~

Get the first items from the collection passing the given truth test.

Interface: `Firstable`_

Signature: ``Collection::first(?callable $callback = null, int $size = 1);``

.. code-block:: php
$generator = static function (): Generator {
yield 'a' => 'a';
yield 'b' => 'b';
yield 'c' => 'c';
yield 'a' => 'd';
yield 'b' => 'e';
yield 'c' => 'f';
};
Collection::fromIterable($generator())
->first(
static function ($value, $key) {
return 'b' === $key;
}
); // ['b' => 'b']
$output = static function (): Generator {
yield 'b' => 'b';
yield 'b' => 'e';
};
Collection::fromIterable($generator())
->first(
static function ($value, $key) {
return 'b' === $key;
},
2
); // ['b' => 'b', 'b' => 'e']
flatten
~~~~~~~

Expand Down Expand Up @@ -1351,11 +1391,6 @@ falsy

Interface: `Falsyable`_

first
~~~~~

Interface: `Firstable`_

foldLeft
~~~~~~~~

Expand Down Expand Up @@ -1425,7 +1460,7 @@ Interface: `Truthyable`_
.. _Explodeable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Explodeable.php
.. _Falsyable: https://github.com/loophp/collection/blob/master/src/Contract/Transformation/Falsyable.php
.. _Filterable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Filterable.php
.. _Firstable: https://github.com/loophp/collection/blob/master/src/Contract/Transformation/Firstable.php
.. _Firstable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Firstable.php
.. _Flattenable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Flattenable.php
.. _Flipable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Flipable.php
.. _array_flip(): https://php.net/array_flip
Expand Down
49 changes: 36 additions & 13 deletions spec/loophp/collection/CollectionSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -836,32 +836,55 @@ public function it_can_get_items_with_only_specific_keys(): void
->shouldIterateAs([0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D', 4 => 'E']);
}

public function it_can_get_its_first_value(): void
public function it_can_get_the_first_item(): void
{
$this::fromIterable(range(1, 10))
->first()
->shouldReturn(1);
->shouldIterateAs([0 => 1]);

$this::fromIterable(range(1, 10))
->first(
static function ($value) {
return 0 === $value % 5;
}
)
->shouldReturn(5);

$this::fromIterable(range(1, 10))
->first(
static function ($value) {
return 0 === $value % 11;
},
'foo'
)
->shouldReturn('foo');
->shouldIterateAs([4 => 5]);

$this::fromIterable([])
->first()
->shouldBe(null);
->shouldIterateAs([]);

$generator = static function (): Generator {
yield 'a' => 'a';

yield 'b' => 'b';

yield 'c' => 'c';

yield 'a' => 'd';

yield 'b' => 'e';

yield 'c' => 'f';
};

$this::fromIterable($generator())
->first(static function ($value, $key) {
return 'b' === $key;
})
->shouldIterateAs(['b' => 'b']);

$output = static function (): Generator {
yield 'b' => 'b';

yield 'b' => 'e';
};

$this::fromIterable($generator())
->first(static function ($value, $key) {
return 'b' === $key;
}, 2)
->shouldIterateAs($output());
}

public function it_can_get_the_last_item(): void
Expand Down
6 changes: 3 additions & 3 deletions src/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
use loophp\collection\Operation\Distinct;
use loophp\collection\Operation\Explode;
use loophp\collection\Operation\Filter;
use loophp\collection\Operation\First;
use loophp\collection\Operation\Flatten;
use loophp\collection\Operation\Flip;
use loophp\collection\Operation\Forget;
Expand Down Expand Up @@ -79,7 +80,6 @@
use loophp\collection\Transformation\Contains;
use loophp\collection\Transformation\Count;
use loophp\collection\Transformation\Falsy;
use loophp\collection\Transformation\First;
use loophp\collection\Transformation\FoldLeft;
use loophp\collection\Transformation\FoldRight;
use loophp\collection\Transformation\Get;
Expand Down Expand Up @@ -327,9 +327,9 @@ public function filter(callable ...$callbacks): CollectionInterface
return $this->run(new Filter(...$callbacks));
}

public function first(?callable $callback = null, $default = null)
public function first(?callable $callback = null, int $size = 1): CollectionInterface
{
return $this->transform(new First($callback, $default));
return $this->run(new First($callback, $size));
}

public function flatten(int $depth = PHP_INT_MAX): CollectionInterface
Expand Down
2 changes: 1 addition & 1 deletion src/Contract/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use loophp\collection\Contract\Operation\Distinctable;
use loophp\collection\Contract\Operation\Explodeable;
use loophp\collection\Contract\Operation\Filterable;
use loophp\collection\Contract\Operation\Firstable;
use loophp\collection\Contract\Operation\Flattenable;
use loophp\collection\Contract\Operation\Flipable;
use loophp\collection\Contract\Operation\Forgetable;
Expand Down Expand Up @@ -71,7 +72,6 @@
use loophp\collection\Contract\Transformation\Allable;
use loophp\collection\Contract\Transformation\Containsable;
use loophp\collection\Contract\Transformation\Falsyable;
use loophp\collection\Contract\Transformation\Firstable;
use loophp\collection\Contract\Transformation\FoldLeftable;
use loophp\collection\Contract\Transformation\FoldRightable;
use loophp\collection\Contract\Transformation\Getable;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

declare(strict_types=1);

namespace loophp\collection\Contract\Transformation;
namespace loophp\collection\Contract\Operation;

use loophp\collection\Contract\Collection;

/**
* @psalm-template TKey
Expand All @@ -16,11 +18,7 @@ interface Firstable
*
* @psalm-param null|callable(T, TKey):(bool) $callback
*
* @param mixed $default
* @psalm-param T|null $default
*
* @return mixed|null
* @psalm-return T|null
* @psalm-return \loophp\collection\Contract\Collection<TKey, T>
*/
public function first(?callable $callback = null, $default = null);
public function first(?callable $callback = null, int $size = 1): Collection;
}
77 changes: 77 additions & 0 deletions src/Operation/First.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

declare(strict_types=1);

namespace loophp\collection\Operation;

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

/**
* @psalm-template TKey
* @psalm-template TKey of array-key
* @psalm-template T
*
* @implements Operation<TKey, T>
*/
final class First extends AbstractOperation implements Operation
{
/**
* @var callable
* @psalm-var callable(T, TKey):(bool)
*/
private $callback;

/**
* @psalm-param callable(T, TKey):(bool)|null $callback
*
* @psalm-param T|null $default
*/
public function __construct(?callable $callback = null, int $size = 1)
{
$defaultCallback =
/**
* @param mixed $value
* @param mixed $key
* @psalm-param T $value
* @psalm-param TKey $key
* @psalm-param Iterator<TKey, T> $iterator
*/
static function ($value, $key, Iterator $iterator): bool {
return true;
};

$this->storage = [
'callback' => $callback ?? $defaultCallback,
'size' => $size,
];
}

public function __invoke(): Closure
{
return
/**
* @psalm-param \Iterator<TKey, T> $iterator
*
* @psalm-return \Generator<TKey, T>
*/
static function (Iterator $iterator, callable $callback, int $size): Generator {
$callback =
/**
* @param mixed $value
* @param mixed $key
* @psalm-param T $value
* @psalm-param TKey $key
* @psalm-param Iterator<TKey, T> $iterator
*/
static function ($value, $key, Iterator $iterator) use ($callback): bool {
return true === $callback($value, $key, $iterator);
};

return yield from (new Run(new Filter($callback), new Limit($size)))($iterator);
};
}
}
74 changes: 0 additions & 74 deletions src/Transformation/First.php

This file was deleted.

0 comments on commit c7ac8b3

Please sign in to comment.