Iterator to array: примеры (PHP)

Преобразование итераторов в массивы с помощью iterator_to_array
Раздел: Итераторы
iterator_to_array(Traversable $iterator, bool $preserve_keys = true): array

Функция iterator_to_array преобразует объект, реализующий интерфейс Traversable (например, итератор или генератор), в обычный массив. Это полезно, когда требуется работать с данными как с массивом, но источник данных предоставляет итератор.

Применение функции

Использование функции актуально в ситуациях, когда операции требуют индексированный или ассоциативный массив, а не объект-итератор. Например, для многократного прохода по данным, случайного доступа к элементам или использования функций для работы с массивами.

Аргументы функции
  • iterator (обязательный): Объект, реализующий интерфейс Traversable.
  • preserve_keys (необязательный): Булевый параметр. При значении true ключи итератора сохраняются. При false или отсутствии параметра - результат будет массивом с числовыми индексами, начиная с нуля.
  • use_keys (необязательный): Доступен с PHP 8.2. Булевый параметр. При значении true ключи, возвращаемые итератором, используются в результирующем массиве. Если false, ключи игнорируются и массив индексируется численно.
Простые примеры использования
Преобразование итератора в численно индексированный массив

Стандартный вызов без второго параметра:

$iterator = new ArrayIterator(['a', 'b', 'c']);
$array = iterator_to_array($iterator);
print_r($array);
Array
(
    [0] => a
    [1] => b
    [2] => c
)
Сохранение ключей итератора

Использование параметра preserve_keys:

$iterator = new ArrayIterator(['first' => 'a', 'second' => 'b']);
$array = iterator_to_array($iterator, true);
print_r($array);
Array
(
    [first] => a
    [second] => b
)
Игнорирование ключей итератора с PHP 8.2

Использование параметра use_keys:

// PHP 8.2 и выше
$iterator = new ArrayIterator([10 => 'x', 20 => 'y']);
$array = iterator_to_array($iterator, use_keys: false);
print_r($array);
Array
(
    [0] => x
    [1] => y
)
Работа с генератором

Генератор также является объектом типа Traversable:

function simpleGenerator() {
    yield 'apple';
    yield 'banana';
}

$array = iterator_to_array(simpleGenerator());
print_r($array);
Array
(
    [0] => apple
    [1] => banana
)
Похожие функции в PHP
Цикл foreach

Прямое использование foreach для итерации без создания массива. Подходит для последовательной обработки элементов без необходимости хранения всего набора данных в памяти одновременно.

Функция iterator_count

Функция iterator_count подсчитывает количество элементов в итераторе. Используется, когда нужен только размер данных, а не сами значения.

Функция get_object_vars

Для объектов, не реализующих Traversable, но когда необходимо получить свойства, может применяться get_object_vars. Функция iterator_to_array работает только с итерируемыми объектами.

Ручное преобразование

Создание массива вручную через foreach дает больше контроля над процессом, например, фильтрацию или преобразование данных на лету.

Критерии выбора: iterator_to_array выбирают для быстрого преобразования итератора в массив. foreach предпочтительнее для обработки больших данных без загрузки в память. iterator_count используют для получения количества элементов.

Аналоги в других языках

Iterator to array в Python

В Python итераторы можно преобразовать в список с помощью функции list() или в словарь с помощью dict().

# Пример с генератором
def simple_gen():
    yield 'a'
    yield 'b'

result_list = list(simple_gen())
print(result_list)  # ['a', 'b']

Iterator to array в Javascript

В современных версиях JavaScript итерируемые объекты можно преобразовать в массив с помощью Array.from() или оператора расширения ....

// Пример с генератором
function* simpleGen() {
    yield 'x';
    yield 'y';
}
const arr = Array.from(simpleGen());
console.log(arr); // ['x', 'y']
// Или с использованием оператора расширения
const arr2 = [...simpleGen()];
console.log(arr2); // ['x', 'y']

Iterator to array в MySQL

Прямого аналога нет. Обычно курсоры (аналоги итераторов) обрабатываются последовательно в процедурах, а результаты SELECT сразу представляются как результирующий набор, который можно воспринимать как таблицу данных.

Основные отличия

В PHP функция явно принимает флаги для управления ключами. В Python и JavaScript преобразование чаще зависит от типа целевой коллекции (список, словарь, массив). Универсальность PHP функции заключается в работе с любым объектом типа Traversable.

Типичные ошибки
Передача неитерируемого объекта

Попытка использовать функцию с объектом, который не реализует интерфейс Traversable.

class NotIterable {}
$obj = new NotIterable();
// Вызовет TypeError
try {
    $array = iterator_to_array($obj);
} catch (TypeError $e) {
    echo $e->getMessage();
}
iterator_to_array(): Argument #1 ($iterator) must be of type Traversable, NotIterable given
Работа с бесконечными генераторами

Преобразование бесконечного генератора приводит к исчерпанию памяти.

function infiniteGenerator() {
    while (true) {
        yield rand();
    }
}
// Приведет к фатальной ошибке из-за нехватки памяти
// $array = iterator_to_array(infiniteGenerator());
Потеря данных при дублировании ключей

Если preserve_keys=true и итератор возвращает дублирующиеся ключи, предыдущие значения перезаписываются.

$iterator = new ArrayIterator(['a', 'b', 'a' => 'c', 'a' => 'd']);
$array = iterator_to_array($iterator, true);
print_r($array);
Array
(
    [0] => a
    [1] => b
    [a] => d
)

Ключ 'a' встретился дважды, в массиве осталось последнее значение 'd'.

История изменений
PHP 8.2

Добавлен третий параметр use_keys. Это позволяет явно указать, следует ли использовать ключи из итератора. Поведение при use_keys: true аналогично preserve_keys: true в предыдущих версиях. Параметр preserve_keys остается для обратной совместимости, но его использование с use_keys может привести к неочевидным результатам.

PHP 8.0

Изменена сигнатура функции для включения типизированных параметров. Ошибки типа теперь вызывают исключение TypeError вместо предупреждений.

Ранние версии

До PHP 5.5 функция не могла корректно обрабатывать генераторы, так как они были добавлены именно в этой версии.

Расширенные примеры
Преобразование итератора FilterIterator

Использование с итераторами, которые фильтруют данные.

Пример php
class NumberFilter extends FilterIterator {
    public function accept(): bool {
        return is_numeric($this->current()) && $this->current() % 2 === 0;
    }
}

$arrayIterator = new ArrayIterator([1, 2, 3, 4, 'apple', 6]);
$filterIterator = new NumberFilter($arrayIterator);
$result = iterator_to_array($filterIterator, false);
print_r($result);
Array
(
    [0] => 2
    [1] => 4
    [2] => 6
)
Комбинация с LimitIterator

Получение части данных из итератора.

Пример php
$iterator = new ArrayIterator(range('A', 'Z'));
$limitIterator = new LimitIterator($iterator, 5, 3); // Смещение 5, лимит 3
$array = iterator_to_array($limitIterator);
print_r($array);
Array
(
    [0] => F
    [1] => G
    [2] => H
)
Обработка итератора с объектами

Итератор может содержать объекты в качестве элементов.

Пример php
class Item {
    public function __construct(public string $name) {}
}

$items = [new Item('Chair'), new Item('Table')];
$iterator = new ArrayIterator($items);
$array = iterator_to_array($iterator);
// Массив содержит те же объекты
print_r($array[0]);
Item Object
(
    [name] => Chair
)
Использование с RecursiveIteratorIterator

Преобразование многоуровневых структур в плоский массив.

Пример php
$multiArray = new RecursiveArrayIterator([1, [2, 3], [4, [5]]]);
$flatIterator = new RecursiveIteratorIterator($multiArray);
$flatArray = iterator_to_array($flatIterator, false);
print_r($flatArray);
Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 4
    [4] => 5
)
Генератор с ключами

Генераторы могут возвращать пары ключ-значение.

Пример php
function keyValueGenerator() {
    yield 'id' => 100;
    yield 'name' => 'John';
    yield 'active' => true;
}

$array = iterator_to_array(keyValueGenerator(), true);
print_r($array);
Array
(
    [id] => 100
    [name] => John
    [active] => 1
)

PHP iterator_to_array function comments

En
Iterator to array Copies the iterator into an array