Есть ли способ перебрать многомерный массив, не зная его глубины?

Пока что, если мне нужно пройти через многомерный массив, я использую цикл foreach для каждого измерения.

например, для двух измерений

foreach($array as $key=>$value)
{
    foreach($value as $k2=>$v2)
    {
         echo
    }
}

Что мне делать, если я не знаю глубину массива? т.е. глубина является переменной.

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

Есть ли способ лучше?

Ответы на вопрос(5)

Вы можете использовать рекурсию для этой проблемы:

Вот один пример

$array = array(1 => array(1 => "a", 2 => array(1 => "b", 2 => "c", 3 => array(1 => "final value"))));

//print_r($array);

printAllValues($array);

function printAllValues($arr) {
    if(!is_array($arr)) {
        echo '<br />' . $arr;
        return;
    }
    foreach($arr as $k => $v) {
        printAllValues($v);
    }
}

Он будет использовать рекурсию для цикла по массиву

Будет печататься как

a
b
c
final value

Вы можете выполнить приведенную ниже функцию для цикла по многомерному массиву без знания его глубины.

// recursive function loop through the dimensional array
function loop($array){

    //loop each row of array
    foreach($array as $key => $value)
    {
         //if the value is array, it will do the recursive
         if(is_array($value) ) $array[$key] =  loop($array[$key]);

         if(!is_array($value)) 
         {
            // you can do your algorithm here
            // example: 
             $array[$key] = (string) $value; // cast value to string data type

         }
    }

    return $array;
}

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

 //array sample to pass to loop() function
 $data = [
  'invoice' => [
      'bill_information' => [
          'price' => 200.00,
          'quantity' => 5
      ],
      'price_per_quantity' => 50.00
  ],
  'user_id' => 20
];

// then you can pass it like this :
$result = loop($data);
var_dump($result);

//it will convert all the value to string for this example purpose

Простая функция внутриarray_walk_recursive чтобы показать уровень вложенности, а также ключи и значения:

array_walk_recursive($array, function($v, $k) {
                                 static $l = 0;
                                 echo "Level " . $l++ . ": $k => $v\n";
                             });

Еще один показываетuse со ссылкой, чтобы получить результат:

array_walk_recursive($array, function($v) use(&$result) {
                                 $result[] = $v;
                             });
 18 июл. 2018 г., 07:17
array_walk_recursive обрабатывает только конечные узлы и пропускает подмассивы. Это было бы неприменимо с приведенным примером.php.net/manual/en/function.array-walk-recursive.php
Решение Вопроса

Да, вы можете использоватьрекурсия, Вот пример, где вы выводите все элементы в массиве:

function printAll($a) {
  if (!is_array($a)) {
    echo $a, ' ';
    return;
  }

  foreach($a as $v) {
    printAll($v);
  }
}

$array = array('hello',
               array('world',
                     '!',
                     array('whats'),
                     'up'),
               array('?'));
printAll($array);

Что вы должныalways помните, что при выполнении рекурсии вам нужноbase case где вы не будете идти дальше.

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

«Расстояние» между вашим текущим входом и базовым случаем называетсяvariant и является целым числом. Вариант должен строго уменьшаться в каждом рекурсивном вызове. Вариант в предыдущем примереthe depth of $a, Если вы не думаете о варианте, вы рискуете получить бесконечные рекурсии, и в итоге сценарий умрет из-запереполнение стека, Весьма часто документировать, что именно представляет собой вариант, в комментарии перед рекурсивными функциями.

 01 дек. 2017 г., 13:38
Нет. Используйте встроенный array_walk_recursive (). PHP отстой при рекурсии.
 18 июл. 2018 г., 07:15
array_walk_recursive обрабатывает только конечные узлы и пропускает подмассивы. Это было бы неприменимо с приведенным примером.php.net/manual/en/function.array-walk-recursive.php

Основываясь на предыдущих примерах рекурсии, вот функция, которая хранит массив путей ключей, под которым находится значение, на случай, если вам нужно знать, как вы туда попали

function recurse($a,$keys=array()) 
    {
        if (!is_array($a)) 
            {
                echo implode("-", $keys)." => $a <br>";
                return;
            }
        foreach($a as $k=>$v) 
            {
                $newkeys = array_merge($keys,array($k));
                recurse($v,$newkeys);
            }
    }


recurse($array);

Ваш ответ на вопрос