PHP итераторы для перебора структур данных

Источник: «PHP Iterators for walking through data structures – FastTips»
Обход, фильтрация и манипулирование данными с помощью итераторов в PHP. Как создавать пользовательские итераторы и фильтры.

PHP итераторы являются важнейшими инструментами для эффективного обхода и манипулирования структурами данных, такими как массивы, объекты и т.д. Они обеспечивают чистый и эффективный способ работы с большими массивами данных без одновременной загрузки всего массива в память. В этой статье мы рассмотрим PHP итераторы и их использование для обхода различных структур данных.

Введение в PHP итераторы

Итератор — это объект, реализующий интерфейс Iterator или IteratorAggregate. Он позволяет перебирать коллекцию элементов по очереди, без необходимости загрузки всей коллекции в память. Это особенно полезно при работе с большими списками, так как экономит память и повышает производительность.

Встроенные PHP итераторы

PHP предоставляет несколько встроенных итераторов для работы с распространёнными структурами данных. Далее в статье мы также рассмотрим, как создавать собственные классы итераторов. Давайте рассмотрим встроенные классы:

ArrayIterator

Итератор ArrayIterator является одним из простейших итераторов и используется для обхода массивов. Рассмотрим пример:

$array = [1, 2, 3, 4, 5];
$iterator = new ArrayIterator($array);
foreach ($iterator as $item) {
echo $item . " ";
}
// Вывод: 1 2 3 4 5

DirectoryIterator

DirectoryIterator полезен для итерации по файлам и каталогам в каталоге. Вот пример использования:

$directory = new DirectoryIterator('/path/to/directory');
foreach ($directory as $fileInfo) {
echo $fileInfo->getFilename() . PHP_EOL;
}

RecursiveIteratorIterator

Итератор RecursiveIteratorIterator используется для рекурсивного перебора вложенных итераторов, например, массивов с вложенными массивами. Он часто используется вместе с RecursiveArrayIterator. Приведём пример:

$nestedArray = [
'item1',
'item2',
['subitem1', 'subitem2'],
'item3',
['subitem3' => ['subsubitem1', 'subsubitem2']],
];
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($nestedArray));
foreach ($iterator as $item) {
echo $item . PHP_EOL;
}

Создание пользовательских итераторов

Вы также можете создавать собственные итераторы, реализуя интерфейс Iterator или IteratorAggregate. Это удобно, когда требуется обход собственных структур данных. Приведём простой пример:

class MyIterator implements Iterator
{
private $data = [1, 2, 3];
private $position = 0;
public function current()
{
return $this->data[$this->position];
}
public function key()
{
return $this->position;
}
public function next()
{
$this->position++;
}
public function rewind()
{
$this->position = 0;
}
public function valid()
{
return isset($this->data[$this->position]);
}
}
$myIterator = new MyIterator();
foreach ($myIterator as $key => $value) {
echo "Key: $key, Value: $value" . PHP_EOL;
}

Фильтрующие итераторы

Фильтрующие итераторы — это подмножество PHP итераторов, позволяющих выполнять итерации над структурами данных с одновременным применением фильтров или условий для включения или исключения элементов. Такая выборочная обработка позволяет оптимизировать код и повысить производительность за счёт сокращения ненужной обработки данных.

PHP предоставляет несколько встроенных итераторов фильтрации. Рассмотрим некоторые из них.

FilterIterator

FilterIterator — это базовый класс для создания собственных итераторов фильтрации. Вы расширяете его и переопределяете метод accept, реализуя свою логику фильтрации. Приведём базовый пример:

class EvenFilter extends \FilterIterator
{
public function accept()
{
// Фильтр чётных чисел
return $this->current() % 2 === 0;
}
}
$array = [1, 2, 3, 4, 5, 6];
$iterator = new EvenFilter(new ArrayIterator($array));
foreach ($iterator as $item) {
echo $item . " "; // Вывод: 2 4 6
}

RegexIterator

RegexIterator позволяет фильтровать элементы на основе регулярных выражений. Обычно используется для фильтрации файлов в каталоге. Приведём пример:

$files = new \DirectoryIterator('/path/to/files');
$regexIterator = new \RegexIterator($files, '/\.txt$/');
foreach ($regexIterator as $fileInfo) {
echo $fileInfo->getFilename() . PHP_EOL;
// Вывод: Только файлы с расширением .txt
}

CallbackFilterIterator

Итератор CallbackFilterIterator позволяет определить пользовательскую логику фильтрации с помощью функции обратного вызова. Это обеспечивает гибкость фильтрации элементов на основе сложных условий. Приведём пример использования:

$array = [10, 20, 30, 40, 50];
$callbackFilter = new \CallbackFilterIterator(
new \ArrayIterator($array),
function ($current, $key, $iterator) {
// Фильтруем элементы больше 30
return $current > 30;
}
);
foreach ($callbackFilter as $item) {
echo $item . " "; // Вывод: 40 50
}

Создание пользовательских фильтрующих итераторов

Чтобы создать собственный фильтрующий итератор, можно расширить класс FilterIterator и реализовать метод accept для определения логики фильтрации. Это особенно удобно, если требуется отфильтровать элементы из собственных структур данных или объектов.

class MyCustomFilter extends \FilterIterator
{
public function accept(): bool
{
// Ваша логика здесь...
}
}

С массивами можно использовать фильтрующие итераторы, как показано в примерах выше. Это удобно для быстрого выбора и обработки конкретных элементов. Они также широко используются для работы с каталогами и файлами. Вы можете фильтровать файлы по расширению, дате модификации, размеру или любым другим критериям, требующимся вашему приложению.

Дополнительные материалы

Предыдущая Статья

Как настроить среду разработки Laravel для Windows без Docker

Следующая Статья

Использование UUID для предотвращения атак методом перебора