From d0ab792fc7e97a38183d9fc01d0d5e98221802de Mon Sep 17 00:00:00 2001 From: Andrej Rypo Date: Mon, 15 Jan 2024 09:43:11 +0100 Subject: [PATCH] Seed --- src/Iterator/Filter.php | 3 +- src/{Iterator/Data.php => Seed.php} | 66 +++++++++++++++-------------- tests/mptree.phpt | 8 ++-- tests/recursive.phpt | 4 +- todo.md | 6 +-- 5 files changed, 45 insertions(+), 42 deletions(-) rename src/{Iterator/Data.php => Seed.php} (76%) diff --git a/src/Iterator/Filter.php b/src/Iterator/Filter.php index bf404c6..0ba72b5 100644 --- a/src/Iterator/Filter.php +++ b/src/Iterator/Filter.php @@ -5,6 +5,7 @@ namespace Dakujem\Oliva\Iterator; use CallbackFilterIterator; +use Dakujem\Oliva\Seed; /** * Filter tree iterator. @@ -24,7 +25,7 @@ public function __construct( callable $accept, ) { parent::__construct( - Data::iterator($input), + Seed::iterator($input), $accept, ); } diff --git a/src/Iterator/Data.php b/src/Seed.php similarity index 76% rename from src/Iterator/Data.php rename to src/Seed.php index 11a1056..aa72e16 100644 --- a/src/Iterator/Data.php +++ b/src/Seed.php @@ -2,37 +2,28 @@ declare(strict_types=1); -namespace Dakujem\Oliva\Iterator; +namespace Dakujem\Oliva; use ArrayIterator; -use Dakujem\Oliva\DataNodeContract; -use Dakujem\Oliva\TreeNodeContract; use Generator; use Iterator; use IteratorIterator; /** - * Iterable data collection helper functions. + * A static tool to manage iterable data collections and iterators. + * + * Contains: + * - methods that produce or adapt iterable data and iterators + * - methods that produce filtering callables to be used with the Filter iterator * * @author Andrej Rypak */ -final class Data +final class Seed { - /** - * Prepend `null` value at the beginning of the data collection. - * Use when missing root. - * Remember, the data accessor and the node factory must be aware that a null may be passed to them. - */ - public static function nullFirst(iterable $input): Generator - { - yield null; - yield from $input; - } - /** * Create a merged iterable. * Can be used to prepend or append data from multiple source collections. - * The data is not actually merged, but a generator is used. + * The data is not actually merged, but a generator is produced. */ public static function merged(iterable ...$input): Generator { @@ -42,13 +33,25 @@ public static function merged(iterable ...$input): Generator } /** - * Create a callable that omits the root node. - * To be used with `Filter` iterator as the predicate: - * @see Filter + * Returns the first element of an iterable collection. */ - public static function omitRoot(): callable + public static function first(iterable $input): mixed { - return fn(TreeNodeContract $node): bool => !$node->isRoot(); + foreach ($input as $item) { + return $item; + } + return null; + } + + /** + * Prepend `null` value at the beginning of the data collection. + * Use when missing root. + * Remember, the data accessor and the node factory must be aware that a null may be passed to them. + */ + public static function nullFirst(iterable $input): Generator + { + yield null; + yield from $input; } /** @@ -62,22 +65,21 @@ public static function omitNull(): callable } /** - * Returns an iterator. - * Useful where en iterator is required. + * Create a filtering callable that omits the root node. + * To be used with `Filter` iterator as the predicate: + * @see Filter */ - public static function iterator(iterable $input): Iterator + public static function omitRoot(): callable { - return is_array($input) ? new ArrayIterator($input) : new IteratorIterator($input); + return fn(TreeNodeContract $node): bool => !$node->isRoot(); } /** - * Returns the first element of an iterable collection. + * Accepts any iterable and returns an iterator. + * Useful where en iterator is required, but any iterable or array is provided. */ - public static function first(iterable $input): mixed + public static function iterator(iterable $input): Iterator { - foreach ($input as $item) { - return $item; - } - return null; + return is_array($input) ? new ArrayIterator($input) : new IteratorIterator($input); } } diff --git a/tests/mptree.phpt b/tests/mptree.phpt index f2a42c5..38015c3 100644 --- a/tests/mptree.phpt +++ b/tests/mptree.phpt @@ -2,11 +2,11 @@ declare(strict_types=1); -use Dakujem\Oliva\Iterator\Data; use Dakujem\Oliva\Iterator\Filter; use Dakujem\Oliva\Iterator\PreOrderTraversal; use Dakujem\Oliva\MaterializedPath\TreeBuilder; use Dakujem\Oliva\Node; +use Dakujem\Oliva\Seed; use Dakujem\Oliva\TreeNodeContract; use Tester\Environment; @@ -35,7 +35,7 @@ $data = [ $builder = new TreeBuilder(); $tree = $builder->buildTree( - input: Data::nullFirst($data), + input: Seed::nullFirst($data), node: fn(?Item $item) => new Node($item), vector: TreeBuilder::fixed( 3, @@ -61,8 +61,8 @@ foreach ($it as $key => $node) { //xdebug_break(); -new Filter($it, Data::omitNull()); -new Filter($it, Data::omitRoot()); +new Filter($it, Seed::omitNull()); +new Filter($it, Seed::omitRoot()); $item = $tree->root()?->data(); diff --git a/tests/recursive.phpt b/tests/recursive.phpt index c577f3c..ec93dd6 100644 --- a/tests/recursive.phpt +++ b/tests/recursive.phpt @@ -2,9 +2,9 @@ declare(strict_types=1); -use Dakujem\Oliva\Iterator\Data; use Dakujem\Oliva\Node; use Dakujem\Oliva\Recursive\TreeBuilder; +use Dakujem\Oliva\Seed; use Tester\Environment; require_once __DIR__ . '/../vendor/autoload.php'; @@ -33,7 +33,7 @@ $data = [ $builder = new TreeBuilder(); $tree = $builder->build( - input: Data::nullFirst($data), + input: Seed::nullFirst($data), node: fn(?Item $item) => new Node($item), self: fn(?Item $item) => $item?->id, parent: fn(?Item $item) => $item?->parent, diff --git a/todo.md b/todo.md index 94c9f88..b9aa1c8 100644 --- a/todo.md +++ b/todo.md @@ -1,12 +1,12 @@ -# A refactor of dakujem/oliva-tree +# A ~~refactor~~ reimplementaion of dakujem/oliva-tree ... after 8+ years - [x] filter - [x] iterating over tree without a real data root -- [ ] recursive tree builder -- [ ] calculus +- [x] recursive tree builder +- [ ] MP tree calculus - [ ] dox