Skip to content

Commit

Permalink
Add new methods: ::combinate() and ::permutate().
Browse files Browse the repository at this point in the history
  • Loading branch information
drupol committed Jan 3, 2020
1 parent 44889cd commit c55a2ef
Show file tree
Hide file tree
Showing 9 changed files with 314 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,7 @@ the methods always return the same values for the same inputs.
| `chunk` | new Collection object | [Chunk.php](./src/Operation/Chunk.php)
| `collapse` | new Collection object | [Collapse.php](./src/Operation/Collapse.php)
| `combine` | new Collection object | [Combine.php](./src/Operation/Combine.php)
| `combinate` | new Collection object | [Combinate.php](./src/Operation/Combinate.php)
| `contains` | boolean | [Contains.php](./src/Transformation/Contains.php)
| `count` | int | [Count.php](./src/Transformation/Count.php)
| `distinct` | new Collection object | [Distinct.php](./src/Operation/Distinct.php)
Expand All @@ -450,6 +451,7 @@ the methods always return the same values for the same inputs.
| `nth` | new Collection object | [Nth.php](./src/Operation/Nth.php)
| `only` | new Collection object | [Only.php](./src/Operation/Only.php)
| `pad` | new Collection object | [Pad.php](./src/Operation/Pad.php)
| `permutate` | new Collection object | [Permutate.php](./src/Operation/Permutate.php)
| `pluck` | new Collection object | [Pluck.php](./src/Operation/Pluck.php)
| `prepend` | new Collection object | [Prepend.php](./src/Operation/Prepend.php)
| `product` | new Collection object | [Product.php](./src/Operation/Product.php)
Expand Down
6 changes: 6 additions & 0 deletions docs/pages/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ collapse
combine
-------

combinate
---------

distinct
--------

Expand Down Expand Up @@ -76,6 +79,9 @@ only
pad
---

permutate
---------

pluck
-----

Expand Down
92 changes: 92 additions & 0 deletions spec/loophp/collection/CollectionSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,58 @@ public function it_can_collapse(): void
->shouldIterateAs(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']);
}

public function it_can_combinate(): void
{
$this::with(range('a', 'c'))
->combinate(0)
->shouldIterateAs(
[
[
0 => 'a',
1 => 'b',
2 => 'c',
],
]
);

$this::with(range('a', 'c'))
->combinate(1)
->shouldIterateAs(
[
[
'a',
],
[
'b',
],
[
'c',
],
]
);

$this::with(range('a', 'c'))
->combinate()
->all()
->shouldBeEqualTo(
[
0 => [
0 => 'a',
1 => 'b',
2 => 'c',
],
1 => [
0 => 'a',
1 => 'c',
],
2 => [
0 => 'b',
1 => 'c',
],
]
);
}

public function it_can_combine(): void
{
$this
Expand Down Expand Up @@ -804,6 +856,46 @@ public function it_can_pad(): void
->shouldIterateAs(['A' => 'A', 'B' => 'B', 'C' => 'C', 'D' => 'D', 'E' => 'E', 0 => 'foo', 1 => 'foo', 2 => 'foo', 3 => 'foo', 4 => 'foo']);
}

public function it_can_permutate(): void
{
$this::with(range('a', 'c'))
->permutate()
->shouldIterateAs(
[
[
0 => 'a',
1 => 'b',
2 => 'c',
],
[
0 => 'a',
1 => 'c',
2 => 'b',
],
[
0 => 'b',
1 => 'a',
2 => 'c',
],
[
0 => 'b',
1 => 'c',
2 => 'a',
],
[
0 => 'c',
1 => 'a',
2 => 'b',
],
[
0 => 'c',
1 => 'b',
2 => 'a',
],
]
);
}

public function it_can_pluck(): void
{
$six = new class() {
Expand Down
22 changes: 22 additions & 0 deletions src/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use loophp\collection\Operation\Apply;
use loophp\collection\Operation\Chunk;
use loophp\collection\Operation\Collapse;
use loophp\collection\Operation\Combinate;
use loophp\collection\Operation\Combine;
use loophp\collection\Operation\Cycle;
use loophp\collection\Operation\Distinct;
Expand All @@ -27,6 +28,7 @@
use loophp\collection\Operation\Nth;
use loophp\collection\Operation\Only;
use loophp\collection\Operation\Pad;
use loophp\collection\Operation\Permutate;
use loophp\collection\Operation\Pluck;
use loophp\collection\Operation\Prepend;
use loophp\collection\Operation\Product;
Expand Down Expand Up @@ -107,6 +109,16 @@ public function collapse(): BaseInterface
return $this->run(new Collapse());
}

/**
* {@inheritdoc}
*
* @return \loophp\collection\Contract\Collection
*/
public function combinate(?int $size = null): BaseInterface
{
return $this->run(new Combinate($size));
}

/**
* {@inheritdoc}
*
Expand Down Expand Up @@ -355,6 +367,16 @@ public function pad(int $size, $value): BaseInterface
return $this->run(new Pad($size, $value));
}

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

/**
* {@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 @@ -16,6 +16,7 @@ interface Collection extends
Base,
Chunkable,
Collapseable,
Combinateable,
Combineable,
Containsable,
Cycleable,
Expand All @@ -38,6 +39,7 @@ interface Collection extends
Nthable,
Onlyable,
Padable,
Permutateable,
Pluckable,
Prependable,
Productable,
Expand Down
20 changes: 20 additions & 0 deletions src/Contract/Combinateable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace loophp\collection\Contract;

/**
* Interface Combinateable.
*/
interface Combinateable
{
/**
* TODO: Combinations.
*
* @param int $size
*
* @return \loophp\collection\Contract\Collection<mixed>
*/
public function combinate(?int $size = null): Base;
}
18 changes: 18 additions & 0 deletions src/Contract/Permutateable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

namespace loophp\collection\Contract;

/**
* Interface Permutateable.
*/
interface Permutateable
{
/**
* TODO: Permutations.
*
* @return \loophp\collection\Contract\Collection<mixed>
*/
public function permutate(): Base;
}
93 changes: 93 additions & 0 deletions src/Operation/Combinate.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

declare(strict_types=1);

namespace loophp\collection\Operation;

use Closure;
use Generator;
use loophp\collection\Contract\Operation;
use loophp\collection\Transformation\All;
use loophp\collection\Transformation\Count;

use function array_slice;
use function count;

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

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

/**
* @param array<mixed> $dataset
* @param int $length
*
* @return Generator<array<mixed>>
*/
public function getCombinations(array $dataset, int $length): Generator
{
$originalLength = count($dataset);
$remainingLength = $originalLength - $length + 1;

for ($i = 0; $i < $remainingLength; ++$i) {
$current = $dataset[$i];

if (1 === $length) {
yield [$current];
} else {
$remaining = array_slice($dataset, $i + 1);

foreach ($this->getCombinations($remaining, $length - 1) as $permutation) {
array_unshift($permutation, $current);

yield $permutation;
}
}
}
}

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

$getPermutation = function (array $dataset, int $length): Generator {
return $this->getCombinations($dataset, $length);
};

return static function () use ($length, $collection, $getPermutation): Generator {
$dataset = (new All())->on($collection);

if (0 < $length) {
return yield from $getPermutation($dataset, $length);
}

$collectionSize = count($dataset);

if (0 === $length) {
return yield from $getPermutation($dataset, $collectionSize);
}

for ($i = 1; $i <= $collectionSize; ++$i) {
yield from $getPermutation($dataset, $i);
}
};
}
}
Loading

0 comments on commit c55a2ef

Please sign in to comment.