Skip to content

Commit

Permalink
distinct() and distinctBy() operators
Browse files Browse the repository at this point in the history
  • Loading branch information
bradynpoulsen committed Nov 7, 2019
1 parent dd01096 commit a0efe70
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 0 deletions.
50 changes: 50 additions & 0 deletions src/Operations/Stateful/DistinctSequence.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace BradynPoulsen\Sequences\Operations\Stateful;

use BradynPoulsen\Sequences\DeferredIterator;
use BradynPoulsen\Sequences\Sequence;
use BradynPoulsen\Sequences\SequenceAlreadyIteratedException;
use BradynPoulsen\Sequences\Traits\CommonOperationsTrait;
use Generator;
use Traversable;

/**
* @internal
*/
final class DistinctSequence implements Sequence
{
use CommonOperationsTrait;

/**
* @var Sequence
*/
private $previous;
/**
* @var callable
*/
private $selector;

public function __construct(Sequence $previous, callable $selector)
{
$this->previous = $previous;
$this->selector = $selector;
}

public function getIterator(): Traversable
{
return new DeferredIterator(function (): Generator {
$seenKeys = [];
$elements = $this->previous->getIterator();
foreach ($elements as $element) {
$key = call_user_func($this->selector, $element);
if (!in_array($key, $seenKeys)) {
yield $element;
array_push($seenKeys, $key);
}
}
});
}
}
23 changes: 23 additions & 0 deletions src/Sequence.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,29 @@ public function constrainOnce(): Sequence;
*/
public function chunked(int $size, ?callable $transform = null): Sequence;

/**
* Returns a sequence containing only distinct elements from this sequence.
*
* @effect intermediate
* @state stateful
*
* @return Sequence Sequence<T> -> Sequence<T>
*/
public function distinct(): Sequence;

/**
* Returns a sequence containing only elements from the given sequence having distinct keys returned
* by the given selector function.
*
* @effect intermediate
* @state stateful
*
* @param callable $selector (T) -> K
*
* @return Sequence Sequence<T> -> Sequence<T>
*/
public function distinctBy(callable $selector): Sequence;

/**
* Returns a sequence contain all elements of this sequence that match the provided $predicate.
*
Expand Down
19 changes: 19 additions & 0 deletions src/Traits/StatefulOperationsTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use BradynPoulsen\Sequences\SequenceOptions;
use BradynPoulsen\Sequences\Operations\Stateful\{
DistinctSequence,
FilteringSequence,
WindowedSequence
};
Expand All @@ -21,6 +22,24 @@ public function chunked(int $size, ?callable $transform = null): Sequence
return $this->windowed($size, $size, SequenceOptions::INCLUDE_PARTIAL_WINDOWS, $transform);
}

/**
* @see Sequence::distinct()
*/
public function distinct(): Sequence
{
return $this->distinctBy(function ($element) {
return $element;
});
}

/**
* @see Sequence::distinctBy()
*/
public function distinctBy(callable $selector): Sequence
{
return new DistinctSequence($this, $selector);
}

/**
* @see Sequence::filter()
*/
Expand Down

0 comments on commit a0efe70

Please sign in to comment.