Skip to content

Commit

Permalink
added MemoizingIterator
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed May 3, 2024
1 parent cf73271 commit c535637
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 0 deletions.
62 changes: 62 additions & 0 deletions src/Iterators/MemoizingIterator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

/**
* This file is part of the Nette Framework (https://nette.org)
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
*/

declare(strict_types=1);

namespace Nette\Iterators;


class MemoizingIterator implements \Iterator
{
private array $cache = [];
private int $index = 0;


public function __construct(
private readonly \Iterator $inner,
) {
}


public function rewind(): void
{
if ($this->index === 0) {
$this->inner->rewind();
} else {
$this->index = 0;
}
}


public function current(): mixed
{
return $this->cache[$this->index][1] ?? null;
}


public function key(): mixed
{
return $this->cache[$this->index][0] ?? null;
}


public function next(): void
{
if (!isset($this->cache[++$this->index])) {
$this->inner->next();
}
}


public function valid(): bool
{
if (!isset($this->cache[$this->index]) && $this->inner->valid()) {
$this->cache[$this->index] = [$this->inner->key(), $this->inner->current()];
}
return isset($this->cache[$this->index]);
}
}
58 changes: 58 additions & 0 deletions tests/Iterators/MemoizingIterator.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

/**
* Test: Nette\Iterators\MemoizingIterator
*/

declare(strict_types=1);

use Nette\Iterators\MemoizingIterator;
use Tester\Assert;

require __DIR__ . '/../bootstrap.php';


function iterator(): Generator
{
yield 'a' => 'apple';
yield ['b'] => ['banana'];
yield 'c' => 'cherry';
}


test('iteration', function () {
$iterator = new MemoizingIterator(iterator());

$pairs = [];
foreach ($iterator as $key => $value) {
$pairs[] = [$key, $value];
}
Assert::same(
[
['a', 'apple'],
[['b'], ['banana']],
['c', 'cherry'],
],
$pairs,
);
});


test('re-iteration', function () {
$iterator = new MemoizingIterator(iterator());

foreach ($iterator as $value);

$pairs = [];
foreach ($iterator as $key => $value) {
$pairs[] = [$key, $value];
}
Assert::same(
[
['a', 'apple'],
[['b'], ['banana']],
['c', 'cherry'],
],
$pairs,
);
});

0 comments on commit c535637

Please sign in to comment.