Skip to content

Commit

Permalink
Add FoldLeft and FoldRight transformations.
Browse files Browse the repository at this point in the history
  • Loading branch information
drupol committed May 26, 2020
1 parent 88fd00f commit b261a89
Show file tree
Hide file tree
Showing 7 changed files with 211 additions and 15 deletions.
64 changes: 49 additions & 15 deletions spec/loophp/collection/CollectionSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,21 @@ static function ($item) {
->shouldIterateAs([1, 2, 3, 4, 5, 6]);
}

public function it_can_be_constructed_from_a_stream(): void
{
$string = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';

$stream = fopen('data://text/plain,' . $string, 'rb');
$this::with($stream)
->count()
->shouldReturn(56);

$stream = fopen('data://text/plain,' . $string, 'rb');
$this::with($stream)
->implode('')
->shouldReturn($string);
}

public function it_can_be_constructed_from_array(): void
{
$this
Expand Down Expand Up @@ -520,6 +535,40 @@ public function it_can_flip(): void
->shouldIterateAs(['a', 'b', 'c', 'd', 'a']);
}

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

$this
->foldLeft(
static function (string $carry, string $item): string {
$carry .= $item;

return $carry;
},
''
)
->shouldReturn('ABC');
}

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

$this
->foldRight(
static function (string $carry, string $item): string {
$carry .= $item;

return $carry;
},
''
)
->shouldReturn('CBA');
}

public function it_can_forget(): void
{
$this
Expand Down Expand Up @@ -1291,19 +1340,4 @@ public function it_is_initializable(): void
{
$this->shouldHaveType(Collection::class);
}

public function it_can_be_constructed_from_a_stream(): void
{
$string = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';

$stream = fopen('data://text/plain,' . $string, 'rb');
$this::with($stream)
->count()
->shouldReturn(56);

$stream = fopen('data://text/plain,' . $string, 'rb');
$this::with($stream)
->implode('')
->shouldReturn($string);
}
}
18 changes: 18 additions & 0 deletions src/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
use loophp\collection\Operation\Filter;
use loophp\collection\Operation\Flatten;
use loophp\collection\Operation\Flip;
use loophp\collection\Operation\FoldLeft;
use loophp\collection\Operation\FoldRight;
use loophp\collection\Operation\Forget;
use loophp\collection\Operation\Intersperse;
use loophp\collection\Operation\Iterate;
Expand Down Expand Up @@ -199,6 +201,22 @@ public function flip(): BaseInterface
return $this->run(new Flip());
}

/**
* {@inheritdoc}
*/
public function foldLeft(callable $callback, $initial = null)
{
return $this->transform(new FoldLeft($callback, $initial));
}

/**
* {@inheritdoc}
*/
public function foldRight(callable $callback, $initial = null)
{
return $this->transform(new FoldRight($callback, $initial));
}

/**
* {@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 @@ -26,6 +26,8 @@ interface Collection extends
Firstable,
Flattenable,
Flipable,
FoldLeftable,
FoldRightable,
Forgetable,
Getable,
Implodeable,
Expand Down
21 changes: 21 additions & 0 deletions src/Contract/FoldLeftable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace loophp\collection\Contract;

/**
* Interface FoldLeftable.
*/
interface FoldLeftable
{
/**
* Fold the collection from the left to the right.
*
* @param callable $callback
* @param mixed $initial
*
* @return mixed
*/
public function foldLeft(callable $callback, $initial = null);
}
21 changes: 21 additions & 0 deletions src/Contract/FoldRightable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace loophp\collection\Contract;

/**
* Interface FoldRightable.
*/
interface FoldRightable
{
/**
* Fold the collection from the right to the left.
*
* @param callable $callback
* @param mixed $initial
*
* @return mixed
*/
public function foldRight(callable $callback, $initial = null);
}
50 changes: 50 additions & 0 deletions src/Operation/FoldLeft.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace loophp\collection\Operation;

use loophp\collection\Contract\Transformation;

/**
* Class FoldLeft.
*/
final class FoldLeft implements Transformation
{
/**
* @var callable
*/
private $callback;

/**
* @var mixed
*/
private $initial;

/**
* FoldLeft constructor.
*
* @param callable $callback
* @param mixed|null $initial
*/
public function __construct(callable $callback, $initial = null)
{
$this->callback = $callback;
$this->initial = $initial;
}

/**
* {@inheritdoc}
*/
public function on(iterable $collection)
{
$callback = $this->callback;
$initial = $this->initial;

foreach ($collection as $key => $value) {
$initial = $callback($initial, $value, $key);
}

return $initial;
}
}
50 changes: 50 additions & 0 deletions src/Operation/FoldRight.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace loophp\collection\Operation;

use loophp\collection\Contract\Transformation;

/**
* Class FoldRight.
*/
final class FoldRight implements Transformation
{
/**
* @var callable
*/
private $callback;

/**
* @var mixed
*/
private $initial;

/**
* FoldRight constructor.
*
* @param callable $callback
* @param mixed|null $initial
*/
public function __construct(callable $callback, $initial = null)
{
$this->callback = $callback;
$this->initial = $initial;
}

/**
* {@inheritdoc}
*/
public function on(iterable $collection)
{
$callback = $this->callback;
$initial = $this->initial;

foreach ((new Reverse())->on($collection)() as $key => $value) {
$initial = $callback($initial, $value, $key);
}

return $initial;
}
}

0 comments on commit b261a89

Please sign in to comment.