Skip to content

Commit

Permalink
feat: add SortIterableAggregate and SortIterator
Browse files Browse the repository at this point in the history
  • Loading branch information
drupol committed Sep 29, 2023
1 parent 82641a8 commit 0c810ab
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 0 deletions.
32 changes: 32 additions & 0 deletions src/SortIterableAggregate.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace loophp\iterators;

use Closure;
use Generator;
use IteratorAggregate;

/**
* @template TKey
* @template T
*
* @implements IteratorAggregate<int, T>
*/
final class SortIterableAggregate implements IteratorAggregate
{
/**
* @param iterable<TKey, T> $iterable
* @param (Closure(T, T): int) $callback
*/
public function __construct(private iterable $iterable, private Closure $callback) {}

/**
* @return Generator<int, T>
*/
public function getIterator(): Generator
{
yield from new SortIterator($this->iterable, $this->callback);
}
}
37 changes: 37 additions & 0 deletions src/SortIterator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace loophp\iterators;

use Closure;
use SplHeap;

/**
* @template TKey
* @template T
*
* @extends SplHeap<T>
*/
final class SortIterator extends SplHeap
{
/**
* @param iterable<TKey, T> $iterable
* @param Closure(T, T): int $callback
*/
public function __construct(private iterable $iterable, private Closure $callback)

This comment has been minimized.

Copy link
@jdreesen

jdreesen Sep 29, 2023

Contributor

The $iterable doesn't need the private as it's only used in the constructor, right?

This comment has been minimized.

Copy link
@drupol

drupol Sep 29, 2023

Author Contributor

Nice catch :), true in this case, the private is not mandatory at all.

{
foreach ($iterable as $value) {
$this->insert($value);
}
}

/**
* @param T $left
* @param T $right
*/
public function compare($left, $right): int

This comment has been minimized.

Copy link
@jdreesen

jdreesen Sep 29, 2023

Contributor

According to the PHP docs this method is protected. Why is it public here?

This comment has been minimized.

Copy link
@drupol

drupol Sep 29, 2023

Author Contributor

Nice catch once again! Looks like 2.4.1 is about to come very soon. Would you like to submit a PR to fix your findings?

This comment has been minimized.

Copy link
@jdreesen

jdreesen Sep 29, 2023

Contributor

Sure, see: #47

{
return ($this->callback)($left, $right);
}
}
51 changes: 51 additions & 0 deletions tests/unit/SortIterableAggregateTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

/**
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

declare(strict_types=1);

namespace tests\loophp\iterators;

use loophp\iterators\SortIterableAggregate;
use PHPUnit\Framework\TestCase;

/**
* @internal
*
* @coversDefaultClass \loophp\iterators
*/
final class SortIterableAggregateTest extends TestCase
{
public function testDoNothing(): void
{
$input = ['a', 'b', 'c', 'd', 'e', 'f'];

$iterator = (new SortIterableAggregate($input, static fn ($right, $left): int => $left <=> $right));

$expected = [];

foreach ($iterator as $value) {
$expected[] = $value;
}

self::assertSame($expected, $input);
}

public function testSimpleSort(): void
{
$input = array_combine(range('c', 'a'), range('c', 'a'));

$iterator = (new SortIterableAggregate($input, static fn ($right, $left): int => $left <=> $right));

$expected = [];

foreach ($iterator as $value) {
$expected[] = $value;
}

self::assertSame($expected, range('a', 'c'));
}
}

0 comments on commit 0c810ab

Please sign in to comment.