Skip to content

Commit

Permalink
Add distinct() dans rsample() methods.
Browse files Browse the repository at this point in the history
  • Loading branch information
drupol committed Sep 3, 2019
1 parent e677738 commit 898a3b1
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 0 deletions.
26 changes: 26 additions & 0 deletions spec/drupol/collection/CollectionSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,18 @@ public function it_can_count_its_items(): void
->shouldReturn(3);
}

public function it_can_distinct(): void
{
$stdclass = new \stdClass();

$this
->beConstructedWith([1, 1, 2, 2, 3, 3, $stdclass, $stdclass]);

$this
->distinct()
->shouldIterateAs([0 => 1, 2 => 2, 4 => 3, 6 => $stdclass]);
}

public function it_can_filter_its_element(): void
{
$input = \array_merge([0, false], \range(1, 10));
Expand Down Expand Up @@ -803,6 +815,20 @@ static function ($carry, $item) {
->shouldIterateAs([0, 1, 3, 6, 10, 15]);
}

public function it_can_rsample(): void
{
$this
->beConstructedThrough('with', [\range(1, 10)]);

$this
->rsample(1)
->shouldHaveCount(10);

$this
->rsample(.5)
->shouldNotHaveCount(10);
}

public function it_can_run_an_operation(Operation $operation): void
{
$square = new class() implements Operation {
Expand Down
27 changes: 27 additions & 0 deletions src/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use drupol\collection\Operation\Combine;
use drupol\collection\Operation\Contains;
use drupol\collection\Operation\Count;
use drupol\collection\Operation\Distinct;
use drupol\collection\Operation\Filter;
use drupol\collection\Operation\First;
use drupol\collection\Operation\Flatten;
Expand Down Expand Up @@ -114,6 +115,18 @@ public function count(): int

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

/**
* {@inheritdoc}
*
* @return \drupol\collection\Contract\Collection
*/
public static function empty(): CollectionInterface
{
Expand Down Expand Up @@ -320,6 +333,20 @@ public function reduction(callable $callback, $initial = null): BaseInterface
return new Collection($this->run(new Reduction($callback, $initial)));
}

/**
* {@inheritdoc}
*
* @return \drupol\collection\Contract\Collection
*/
public function rsample($probability): BaseInterface
{
$callback = static function ($item) use ($probability) {
return (\mt_rand() / \mt_getrandmax()) < $probability;
};

return new Collection($this->run(new Filter($callback)));
}

/**
* {@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
Collapseable,
Combineable,
Containsable,
Distinctable,
Filterable,
Firstable,
Flattenable,
Expand All @@ -38,6 +39,7 @@ interface Collection extends
Rebaseable,
Reduceable,
Reductionable,
RSampleable,
Skipable,
Sliceable,
Sortable,
Expand Down
16 changes: 16 additions & 0 deletions src/Contract/Distinctable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace drupol\collection\Contract;

/**
* Interface Distinctable.
*/
interface Distinctable
{
/**
* @return \drupol\collection\Contract\Base
*/
public function distinct(): Base;
}
18 changes: 18 additions & 0 deletions src/Contract/RSampleable.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 RSampleable.
*/
interface RSampleable
{
/**
* @param float $probability
*
* @return \drupol\collection\Contract\Base
*/
public function rsample($probability): Base;
}
36 changes: 36 additions & 0 deletions src/Operation/Distinct.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace drupol\collection\Operation;

use drupol\collection\Collection;
use drupol\collection\Contract\Operation;

/**
* Class Distinct.
*/
final class Distinct implements Operation
{
/**
* {@inheritdoc}
*/
public function on(iterable $collection)
{
return static function () use ($collection) {
$seen = new Collection([]);

foreach ($collection as $key => $value) {
if (true === $seen->contains($value)) {
continue;
}

$seen = $seen
->append($value)
->rebase();

yield $key => $value;
}
};
}
}

0 comments on commit 898a3b1

Please sign in to comment.