Skip to content

Commit

Permalink
feat: Add new Iterator aggregates.
Browse files Browse the repository at this point in the history
  • Loading branch information
drupol committed Jan 28, 2022
1 parent f88c556 commit 04db72d
Show file tree
Hide file tree
Showing 5 changed files with 267 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ The missing PHP iterators.
* `CachingIteratorAggregate`
* `ClosureIterator`: `ClosureIterator(callable $callable, array $arguments = [])`
* `ClosureIteratorAggregate`: `ClosureIteratorAggregate(callable $callable, array $arguments = [])`
* `ConcatIterableAggregate`
* `IterableIterator`: `IterableIterator(iterable $iterable)`
* `IterableIteratorAggregate`: `IterableIteratorAggregate(iterable $iterable)`
* `MultipleIterableAggregate`
* `PackIterableAggregate`
* `PausableIteratorAggregate`
* `RandomIterableAggregate`
Expand Down
53 changes: 53 additions & 0 deletions src/ConcatIterableAggregate.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?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 loophp\iterators;

use AppendIterator;
use Generator;
use IteratorAggregate;
use NoRewindIterator;

/**
* @template TKey
* @template T
*
* @implements IteratorAggregate<TKey, T>
*/
final class ConcatIterableAggregate implements IteratorAggregate
{
/**
* @var iterable<mixed, iterable<TKey, T>>
*/
private iterable $iterables;

/**
* @param iterable<mixed, iterable<TKey, T>> $iterables
*/
public function __construct(iterable $iterables)
{
$this->iterables = $iterables;
}

/**
* @return Generator<TKey, T>
*/
public function getIterator(): Generator
{
$iterator = new AppendIterator();

foreach ($this->iterables as $iterable) {
$iterator->append(
new NoRewindIterator((new IterableIteratorAggregate($iterable))->getIterator())
);
}

yield from $iterator;
}
}
60 changes: 60 additions & 0 deletions src/MultipleIterableAggregate.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?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 loophp\iterators;

use Generator;
use IteratorAggregate;
use MultipleIterator;
use Traversable;

/**
* @template TKey
* @template T
*
* @implements IteratorAggregate<int, array<TKey, T>>
*/
final class MultipleIterableAggregate implements IteratorAggregate
{
/**
* @var (0|1|2|3)
*/
private int $flags;

/**
* @var iterable<mixed, iterable<TKey, T>>
*/
private iterable $iterables;

/**
* @param iterable<mixed, iterable<TKey, T>> $iterables
* @param (0|1|2|3) $flags
*/
public function __construct(iterable $iterables, int $flags = MultipleIterator::MIT_NEED_ALL | MultipleIterator::MIT_KEYS_NUMERIC)
{
$this->flags = $flags;
$this->iterables = $iterables;
}

/**
* @return Generator<int, array<TKey, T>>
*/
public function getIterator(): Traversable
{
$mit = new MultipleIterator($this->flags);

foreach ($this->iterables as $iterable) {
$mit->attachIterator(
(new IterableIteratorAggregate($iterable))->getIterator()
);
}

yield from $mit;
}
}
38 changes: 38 additions & 0 deletions tests/unit/ConcatIterableAggregateTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?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 ArrayIterator;
use loophp\iterators\ConcatIterableAggregate;
use loophp\iterators\NormalizeIterableAggregate;
use PHPUnit\Framework\TestCase;

/**
* @internal
* @coversDefaultClass \loophp\iterators
*/
final class ConcatIterableAggregateTest extends TestCase
{
public function testBasic(): void
{
$generator = static function () {
yield from range('a', 'c');
};
$iterator = new ArrayIterator(range('d', 'f'));
$array = range('g', 'i');

$iterator = new NormalizeIterableAggregate(
new ConcatIterableAggregate([$generator(), $iterator, $array])
);

$expected = range('a', 'i');
self::assertSame($expected, iterator_to_array($iterator));
}
}
114 changes: 114 additions & 0 deletions tests/unit/MultipleIterableAggregateTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<?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 ArrayIterator;
use loophp\iterators\MultipleIterableAggregate;
use loophp\iterators\NormalizeIterableAggregate;
use MultipleIterator;
use PHPUnit\Framework\TestCase;

/**
* @internal
* @coversDefaultClass \loophp\iterators
*/
final class MultipleIterableAggregateTest extends TestCase
{
public function basicProvider()
{
$generator = static function () {
yield from range('a', 'c');
};
$iterator = new ArrayIterator(range('d', 'f'));
$array = range('g', 'i');

yield [
[$generator(), $iterator, $array],
[
[
'a',
'd',
'g',
],
[
'b',
'e',
'h',
],
[
'c',
'f',
'i',
],
],
];
}

public function basicWithFlagsProvider()
{
yield [
[range('a', 'c'), range('d', 'e')],
MultipleIterator::MIT_NEED_ALL,
[
[
'a',
'd',
],
[
'b',
'e',
],
],
];

yield [
[range('a', 'c'), range('d', 'e')],
MultipleIterator::MIT_NEED_ANY,
[
[
'a',
'd',
],
[
'b',
'e',
],
[
'c',
null,
],
],
];
}

/**
* @dataProvider basicProvider
*/
public function testBasic(array $iterables, array $expected): void
{
$iterator = new NormalizeIterableAggregate(
new MultipleIterableAggregate($iterables)
);

self::assertSame($expected, iterator_to_array($iterator));
}

/**
* @dataProvider basicWithFlagsProvider
*/
public function testFlags(array $iterables, int $flags, array $expected): void
{
$iterator = new NormalizeIterableAggregate(
new MultipleIterableAggregate($iterables, $flags)
);

self::assertSame($expected, iterator_to_array($iterator));
}
}

0 comments on commit 04db72d

Please sign in to comment.