Skip to content

Commit

Permalink
feat: Add Duplicate operation.
Browse files Browse the repository at this point in the history
  • Loading branch information
drupol committed Sep 14, 2020
1 parent da6caa9 commit b2d2a82
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 0 deletions.
24 changes: 24 additions & 0 deletions docs/pages/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,29 @@ Signature: ``Collection::dropWhile(callable $callback);``
Collection::fromIterable([1,2,3,4,5,6,7,8,9,1,2,3])
->dropWhile($isSmallerThanThree); // [3,4,5,6,7,8,9,1,2,3]
duplicate
~~~~~~~~~

Find duplicated values from the collection.

Interface: `Duplicateable`_

Signature: ``Collection::duplicate();``

.. code-block:: php
// It might returns duplicated values !
Collection::fromIterable(['a', 'b', 'c', 'a', 'c', 'a'])
->duplicate(); // [3 => 'a', 4 => 'c', 5 => 'a']
// Use ::distinct() and ::normalize() to get what you want.
Collection::fromIterable(['a', 'b', 'c', 'a', 'c', 'a'])
->duplicate()
->distinct()
->normalize() // [0 => 'a', 1 => 'c']
explode
~~~~~~~

Expand Down Expand Up @@ -1606,6 +1629,7 @@ Signature: ``Collection::zip(iterable ...$iterables);``
.. _Distinctable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Distinctable.php
.. _Dropable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Dropable.php
.. _DropWhileable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/DropWhileable.php
.. _Duplicateable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Duplicateable.php
.. _Explodeable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Explodeable.php
.. _Falsyable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Falsyable.php
.. _Filterable: https://github.com/loophp/collection/blob/master/src/Contract/Operation/Filterable.php
Expand Down
13 changes: 13 additions & 0 deletions spec/loophp/collection/CollectionSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,19 @@ public function it_can_dropWhile(): void
]);
}

public function it_can_duplicate(): void
{
$result = static function () {
yield 3 => 'a';

yield 4 => 'c';
};

$this::fromIterable(['a', 'b', 'c', 'a', 'c'])
->duplicate()
->shouldIterateAs($result());
}

public function it_can_explode(): void
{
$string = 'I am just a random piece of text.';
Expand Down
6 changes: 6 additions & 0 deletions src/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
use loophp\collection\Operation\Distinct;
use loophp\collection\Operation\Drop;
use loophp\collection\Operation\DropWhile;
use loophp\collection\Operation\Duplicate;
use loophp\collection\Operation\Explode;
use loophp\collection\Operation\Falsy;
use loophp\collection\Operation\Filter;
Expand Down Expand Up @@ -347,6 +348,11 @@ public function dropWhile(callable $callback): CollectionInterface
return $this->run(DropWhile::of()($callback));
}

public function duplicate(): CollectionInterface
{
return $this->run(Duplicate::of());
}

public static function empty(): Collection
{
return new self();
Expand Down
3 changes: 3 additions & 0 deletions src/Contract/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
use loophp\collection\Contract\Operation\Distinctable;
use loophp\collection\Contract\Operation\Dropable;
use loophp\collection\Contract\Operation\DropWhileable;
use loophp\collection\Contract\Operation\Duplicateable;
use loophp\collection\Contract\Operation\Explodeable;
use loophp\collection\Contract\Operation\Falsyable;
use loophp\collection\Contract\Operation\Filterable;
Expand Down Expand Up @@ -113,6 +114,7 @@
* @template-extends Distinctable<TKey, T>
* @template-extends Dropable<TKey, T>
* @template-extends DropWhileable<TKey, T>
* @template-extends Duplicateable<TKey, T>
* @template-extends Explodeable<TKey, T>
* @template-extends Filterable<TKey, T>
* @template-extends Firstable<TKey, T>
Expand Down Expand Up @@ -190,6 +192,7 @@ interface Collection extends
Distinctable,
Dropable,
DropWhileable,
Duplicateable,
Explodeable,
Falsyable,
Filterable,
Expand Down
20 changes: 20 additions & 0 deletions src/Contract/Operation/Duplicateable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?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 Duplicateable
{
/**
* @psalm-return \loophp\collection\Contract\Collection<TKey, T>
*/
public function duplicate(): Collection;
}
43 changes: 43 additions & 0 deletions src/Operation/Duplicate.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

namespace loophp\collection\Operation;

use Closure;
use Generator;
use Iterator;

use function in_array;

/**
* @psalm-template TKey
* @psalm-template TKey of array-key
* @psalm-template T
*/
final class Duplicate extends AbstractOperation
{
/**
* @psalm-return Closure(Iterator<TKey, T>): Generator<TKey, T>
*/
public function __invoke(): Closure
{
return
/**
* @psalm-param Iterator<TKey, T> $iterator
*
* @psalm-return Generator<TKey, T>
*/
static function (Iterator $iterator): Generator {
$stack = [];

foreach ($iterator as $key => $value) {
if (true === in_array($value, $stack, true)) {
yield $key => $value;
}

$stack[] = $value;
}
};
}
}

0 comments on commit b2d2a82

Please sign in to comment.