Как пропустить первый элемент итератора в цикле? А пройти пять начиная с третьего?



💩 if (!isset($firstSkipped))

💩 if ($i++ < 2)



Все гораздо проще и лаконичнее с LimitIterator.

foreach (new LimitIterator($iterator, $offset = 2, $limit = 5) as $item) {

// ...

}




Обратите внимание, что первый аргумент LimitIterator имеет тип Iterator. То есть можно передать, например, Generator или ArrayIterator. Однако часто простые обходимые объекты реализуют IteratorAggregate, который не является подтипом Iterator. Как тут быть? Сначала на ум приходит забрать из него итератор вызовом $object->getIterator(). Она неверная, потому что IteratorAggregate::getIterator возвращает супертип Traversable, то есть это опять-таки может быть IteratorAggregate. Правильное решение — обернуть наш объект в IteratorIterator, который превращает любой Traversable в Iterator.



Итак, проход по первым трём элементам любого обходимого объекта будет выглядеть так:

foreach (new LimitIterator(new IteratorIterator($traversable), 0, 3) as $item) {

// ...

}




Неплохие базовые вопросы для собеседования 😉