Перебор вложенных массивов в PHP

#php #arrays

#php #массивы

Вопрос:

У меня есть очень сложный массив, который мне нужно перебрать.

 Array(

  [1] => Array(

    [1] => ""
    [2] => Array(

      [1] => ""
      [2] => Array(

        [1] => ""

      )

    )

  )

)
  

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

В этом массиве представлены комментарии и ответы, где ответы могут содержать больше ответов.

Есть мысли?

Комментарии:

1. если вы не знаете глубину вложенности, то вам, вероятно, нужна рекурсивная функция

2. Напишите рекурсивную функцию или эквивалент с циклом: начните с пустого стека (массива), цикл извлекает верхний элемент и обрабатывает его, при обработке, если вы найдете какие-либо подмассивы, затем помещайте их в стек. Повторяйте, пока стек не опустеет.

3. Зависит от того, что вам нужно делать с данными и нужно ли вам знать их положение в массиве. Можете ли вы привести конкретный пример с результатами, которые вам нужны.

Ответ №1:

Вы могли бы использовать a RecursiveArrayIterator , который является частью PHP SPL, поставляемый необязательным, с ядром PHP.

 <?php

$arr = [
    'lvl1-A' => [
        'lvl2' => [
            'lvl3' => 'done'
        ],
    ],
    'lvl1-B' => 'done',
];

function traverse( Traversable $it ): void {
    while ( $it->valid() ) {
        $it->hasChildren() 
            ? print "{$it->key()} => n" and traverse( $it->getChildren() ) 
            : print "{$it->key()} => {$it->current()}n";
        $it->next();
    }
}

$it = new RecursiveArrayIterator( $arr );
$it->rewind();
traverse( $it );
print 'Done.';
  

Запустите и воспроизведите этот пример в REPL здесь: https://3v4l.org/cGtoi

Код предназначен только для подробного объяснения того, что вы можете ожидать увидеть. Итератор проходит каждый уровень. Как вы на самом деле это кодируете, зависит от вас. Имейте в виду, что фильтрация или выравнивание массива (читай: его предварительное преобразование) может быть другим вариантом. Вы могли бы также использовать генератор и генерировать каждый уровень и, возможно, использовать совместную многозадачность / сопрограммы, как объяснил сопровождающий PHP core Никич в своем сообщении в блоге.

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

В случае, если вам действительно нужно действовать быстро, рассмотрите возможность потоковой передачи результата, чтобы вы могли обрабатывать выходные данные, пока вы все еще работаете над обработкой входного массива.

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

Ответ №2:

Случай довольно сложный, поскольку вы have to выполняете цикл, но по некоторым причинам вы не можете или не хотите этого делать:

… что мне нужно перебрать

и

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

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

Если по каким-то причинам это не вариант, вы можете рассмотреть возможность:

  • как-то разделите этот большой массив на меньшие массивы
  • проверьте, как это работает, json_encode и проанализируйте строку с str_* помощью функций и регулярных выражений

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

Предполагая, с другой стороны, что вы могли бы выполнить цикл. Что может вас беспокоить? Использование памяти, сколько времени это займет и т.д.? Вы всегда можете использовать cron для ежедневного запуска и т. Д. Но самое главное — найти причину, по которой вы в итоге получили огромный массив.