Skip to content

Commit 0c810ab

Browse files
committed
feat: add SortIterableAggregate and SortIterator
1 parent 82641a8 commit 0c810ab

File tree

3 files changed

+120
-0
lines changed

3 files changed

+120
-0
lines changed

src/SortIterableAggregate.php

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace loophp\iterators;
6+
7+
use Closure;
8+
use Generator;
9+
use IteratorAggregate;
10+
11+
/**
12+
* @template TKey
13+
* @template T
14+
*
15+
* @implements IteratorAggregate<int, T>
16+
*/
17+
final class SortIterableAggregate implements IteratorAggregate
18+
{
19+
/**
20+
* @param iterable<TKey, T> $iterable
21+
* @param (Closure(T, T): int) $callback
22+
*/
23+
public function __construct(private iterable $iterable, private Closure $callback) {}
24+
25+
/**
26+
* @return Generator<int, T>
27+
*/
28+
public function getIterator(): Generator
29+
{
30+
yield from new SortIterator($this->iterable, $this->callback);
31+
}
32+
}

src/SortIterator.php

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace loophp\iterators;
6+
7+
use Closure;
8+
use SplHeap;
9+
10+
/**
11+
* @template TKey
12+
* @template T
13+
*
14+
* @extends SplHeap<T>
15+
*/
16+
final class SortIterator extends SplHeap
17+
{
18+
/**
19+
* @param iterable<TKey, T> $iterable
20+
* @param Closure(T, T): int $callback
21+
*/
22+
public function __construct(private iterable $iterable, private Closure $callback)
23+
{
24+
foreach ($iterable as $value) {
25+
$this->insert($value);
26+
}
27+
}
28+
29+
/**
30+
* @param T $left
31+
* @param T $right
32+
*/
33+
public function compare($left, $right): int
34+
{
35+
return ($this->callback)($left, $right);
36+
}
37+
}
+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
/**
4+
* For the full copyright and license information, please view
5+
* the LICENSE file that was distributed with this source code.
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace tests\loophp\iterators;
11+
12+
use loophp\iterators\SortIterableAggregate;
13+
use PHPUnit\Framework\TestCase;
14+
15+
/**
16+
* @internal
17+
*
18+
* @coversDefaultClass \loophp\iterators
19+
*/
20+
final class SortIterableAggregateTest extends TestCase
21+
{
22+
public function testDoNothing(): void
23+
{
24+
$input = ['a', 'b', 'c', 'd', 'e', 'f'];
25+
26+
$iterator = (new SortIterableAggregate($input, static fn ($right, $left): int => $left <=> $right));
27+
28+
$expected = [];
29+
30+
foreach ($iterator as $value) {
31+
$expected[] = $value;
32+
}
33+
34+
self::assertSame($expected, $input);
35+
}
36+
37+
public function testSimpleSort(): void
38+
{
39+
$input = array_combine(range('c', 'a'), range('c', 'a'));
40+
41+
$iterator = (new SortIterableAggregate($input, static fn ($right, $left): int => $left <=> $right));
42+
43+
$expected = [];
44+
45+
foreach ($iterator as $value) {
46+
$expected[] = $value;
47+
}
48+
49+
self::assertSame($expected, range('a', 'c'));
50+
}
51+
}

0 commit comments

Comments
 (0)