Skip to content

Commit

Permalink
Add Tail and Reverse Operations.
Browse files Browse the repository at this point in the history
  • Loading branch information
drupol committed Dec 23, 2019
1 parent a80afcd commit bae14bf
Show file tree
Hide file tree
Showing 8 changed files with 177 additions and 0 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,17 @@ Collection::with(['A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E'])
)
->all(); // [0 => 'a', 1 => 'b', 2 => 'c', 3 = >'d', 4 => 'e']

// Tail
Collection::with(range('a', 'z'))
->tail(3)
->all(); // [23 => 'x', 24 => 'y', 25 => 'z']

// Reverse
Collection::with(range('a', 'z'))
->tail(4)
->reverse()
->all(); // [25 => 'z', 24 => 'y', 23 => 'x', 22 => 'w']

Collection::with(['A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E'])
->walk(
static function ($value, $key) {
Expand Down
32 changes: 32 additions & 0 deletions spec/drupol/collection/CollectionSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -918,6 +918,20 @@ static function ($carry, $item) {
->shouldIterateAs([0, 1, 3, 6, 10, 15]);
}

public function it_can_reverse(): void
{
$this
->beConstructedThrough('with', [range('A', 'F')]);

$this
->reverse()
->shouldIterateAs([5 => 'F', 4 => 'E', 3 => 'D', 2 => 'C', 1 => 'B', 0 => 'A']);

$this
->skip(3, 3)
->shouldIterateAs([]);
}

public function it_can_rsample(): void
{
$this
Expand Down Expand Up @@ -1066,6 +1080,24 @@ public function it_can_split(): void
->shouldIterateAs([0 => [1, 2, 3], 1 => [4, 5, 6], 2 => [7, 8, 9], 3 => [10, 11, 12], 4 => [13, 14, 15]]);
}

public function it_can_tail(): void
{
$this
->beConstructedThrough('with', [range('A', 'F')]);

$this
->tail(3)
->shouldIterateAs([3 => 'D', 4 => 'E', 5 => 'F']);

$this
->tail(-5)
->shouldIterateAs([]);

$this
->tail(100)
->shouldIterateAs(range('A', 'F'));
}

public function it_can_until(): void
{
$collatz = static function (int $initial = 1): int {
Expand Down
22 changes: 22 additions & 0 deletions src/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@
use drupol\collection\Operation\Prepend;
use drupol\collection\Operation\Range;
use drupol\collection\Operation\Reduction;
use drupol\collection\Operation\Reverse;
use drupol\collection\Operation\Scale;
use drupol\collection\Operation\Skip;
use drupol\collection\Operation\Slice;
use drupol\collection\Operation\Sort;
use drupol\collection\Operation\Split;
use drupol\collection\Operation\Tail;
use drupol\collection\Operation\Until;
use drupol\collection\Operation\Walk;
use drupol\collection\Operation\Zip;
Expand Down Expand Up @@ -410,6 +412,16 @@ public function reduction(callable $callback, $initial = null): BaseInterface
return $this->run(new Reduction($callback, $initial));
}

/**
* {@inheritdoc}
*
* @return \drupol\collection\Contract\Collection
*/
public function reverse(): BaseInterface
{
return $this->run(new Reverse());
}

/**
* {@inheritdoc}
*
Expand Down Expand Up @@ -477,6 +489,16 @@ public function split(callable ...$callbacks): BaseInterface
return $this->run(new Split(...$callbacks));
}

/**
* {@inheritdoc}
*
* @return \drupol\collection\Contract\Collection
*/
public function tail(int $length): BaseInterface
{
return $this->run(new Tail($length));
}

/**
* {@inheritdoc}
*
Expand Down
2 changes: 2 additions & 0 deletions src/Contract/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,14 @@ interface Collection extends
Rebaseable,
Reduceable,
Reductionable,
Reverseable,
RSampleable,
Scaleable,
Skipable,
Sliceable,
Sortable,
Splitable,
Tailable,
Untilable,
Walkable,
Zipable
Expand Down
18 changes: 18 additions & 0 deletions src/Contract/Reverseable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

namespace drupol\collection\Contract;

/**
* Interface Reverseable.
*/
interface Reverseable
{
/**
* TODO.
*
* @return \drupol\collection\Contract\Collection<mixed>
*/
public function reverse(): Base;
}
18 changes: 18 additions & 0 deletions src/Contract/Tailable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

namespace drupol\collection\Contract;

/**
* Interface Tailable.
*/
interface Tailable
{
/**
* @param int $length
*
* @return \drupol\collection\Contract\Collection<mixed>
*/
public function tail(int $length): Base;
}
30 changes: 30 additions & 0 deletions src/Operation/Reverse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace drupol\collection\Operation;

use Closure;
use drupol\collection\Contract\Operation;
use drupol\collection\Transformation\All;
use Generator;

/**
* Class Reverse.
*/
final class Reverse implements Operation
{
/**
* {@inheritdoc}
*/
public function on(iterable $collection): Closure
{
return static function () use ($collection): Generator {
$all = (new All())->on($collection);

for (end($all); null !== ($key = key($all)); prev($all)) {
yield $key => current($all);
}
};
}
}
44 changes: 44 additions & 0 deletions src/Operation/Tail.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

declare(strict_types=1);

namespace drupol\collection\Operation;

use Closure;
use drupol\collection\Contract\Operation;
use drupol\collection\Transformation\Count;
use Generator;

/**
* Class Tail.
*/
final class Tail implements Operation
{
/**
* @var int
*/
private $length;

/**
* Tail constructor.
*
* @param int $length
*/
public function __construct(int $length)
{
$this->length = $length;
}

/**
* {@inheritdoc}
*/
public function on(iterable $collection): Closure
{
$offset = (new Count())->on($collection) - $this->length;
$length = $this->length;

return static function () use ($offset, $length, $collection): Generator {
yield from (new Limit($length))->on((new Skip($offset))->on($collection)())();
};
}
}

0 comments on commit bae14bf

Please sign in to comment.