Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add RecursiveIteratorAggregateIterator #56

Closed

Conversation

mastir
Copy link

@mastir mastir commented Jul 26, 2024

One more missing iterator.

I made it to travel deep tree Traversable structure without RecursiveIterator interface

@mastir mastir requested a review from drupol as a code owner July 26, 2024 11:59
Copy link

what-the-diff bot commented Jul 26, 2024

PR Summary

  • Introduction of New Recursive Iterator Class
    A new class called 'RecursiveIteratorAggregateIterator' has been created and included in a new file. This class is designed to handle how lists or other sets of data are stepped through, especially if these sets contain other nested sets.
  • Unit Test for New Recursive Iterator Class
    To validate the functionality of the new Recursive Iterator class, a series of unit tests have been created and captured in a file called 'RecursiveIteratorAggregateIteratorTest'.
  • Expansion of Unit Test to Cover New Cases
    The already-existing 'RecursiveIteratorAggregateIteratorTest' was updated to include a new case called 'testRecursiveIteratorAggregateIterator'. This additional test is designed to ensure that the new class correctly handles a series of nested objects.

@drupol
Copy link
Contributor

drupol commented Jul 26, 2024

hey hi first contributor!

Thanks for the PR! Can you please fix the static analysis issue and code style?

Once it's done, I'll review it manually.

Thanks again!

src/RecursiveIteratorAggregateIterator.php Outdated Show resolved Hide resolved
src/RecursiveIteratorAggregateIterator.php Outdated Show resolved Hide resolved
src/RecursiveIteratorAggregateIterator.php Outdated Show resolved Hide resolved
Comment on lines 53 to 56
$current = end($this->stack)->current();

yield $current;
end($this->stack)->next();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

end() is a $\mathcal{O}(n)$ operation, it may be slow, let's try to call it once here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can simple have last $iterator outside of a $stack to avoid array operations


yield $current;
end($this->stack)->next();
$this->stack[] = self::findIterator($current);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not need to have a static function self::findIterator, let's remove the static from it.

public function getIterator(): Generator
{
$iterator = $this->findIterator($this->input);
$this->stack = [];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's keep the object immutable, this should not happen

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can`t have state tracking (getDepth) on immutable iterator, we can add exception here

*/
public function __construct(private readonly Traversable $input) {}

public function getDepth(): int
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The getDepth method is not part of the IteratorAggregate interface, I would remove it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getDepth method is required for tree travel

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then it should be private.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It`s not used by iterator, its required to detect depth (or move direction) in loop. Like

foreach($it as $val){
   echo str_repeat('-', $it->getDepth()).$val."\n";
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes I noticed it after your message. Since that method is not part of the interface, I would make it private.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or more common use case for xml/html/whatever

$prev_depth = 0;
foreach($it as $val){
   $next_depth = $it->getDepth();
   if ($prev_depth < $next_depth) echo "<tag>\n";
   for($i=$prev_depth;$i>$next_depth;$i--) echo "</tag>\n";
   echo $val;
   $prev_depth = $next_depth;
}
for($i=$prev_depth;$i>0;$i--) echo "</tag>\n";

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private method cannot be called outside of the iterator class (including foreach loop). It`s simple useless

public function getIterator(): Generator
{
if (null !== $this->stack) {
throw new RuntimeException('Iterator already active ');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This cannot happen. This method always returns a new iterator, ready to be consumed.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

foreach($it as $a){ //generator assign stack to iterator
    foreach($it as $b){ //same iterator, new stack will replace original, throw exception
    }
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are you trying to tell me here?

Copy link
Author

@mastir mastir Jul 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exception will be thrown in this case

@drupol
Copy link
Contributor

drupol commented Oct 9, 2024

Does this PR is similar to #61 ?

@mastir
Copy link
Author

mastir commented Oct 9, 2024

Yes, #61 has same logic, but for different structeres. this iterator provides recursive iteration over tree-like structure of objects implementing Itrator or IteratorArgregate interface. RecursiveIterableAggregate in #61 adds iteration over traversable tree-like structures (like deep array or array of object tree).

Copy link

Since this pull request has not had any activity within the last 5 days, I have marked it as stale.
I will close it if no further activity occurs within the next 5 days.

@github-actions github-actions bot added the stale label Oct 15, 2024
@github-actions github-actions bot closed this Oct 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants