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 с красивыми URL-адресами (без Docker)

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

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