PHP foreach () с массивами внутри массивов?

Я хочу вызвать функцию для каждого элемента массива. Это очевидно очень легко с foreach() , но я начинаю ломаться, когда массивы содержат массивы. Может ли кто-нибудь помочь мне с функцией, которая выполнит некоторый код для каждой пары ключ -> значение из набора массивов внутри массивов. Глубина могла бы, теоретически, быть бесконечной, но хорошим пределом было бы 3 итерации (массив в массиве в массиве), если рекурсия не могла работать.

Пример массива будет взято из $ _POST ниже:

 массив
 (
     [Языки] => Массив
     (
         [0] => php
         [1] => mysql
         [2] => взлом
     )

     [ставки] => Массив
     (
         [incall] => Массив
         (
             [1hr] => 10
         )

         [outcall] => Массив
         (
             [1hr] => 10
         )

     )
 )

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

 [0] => php
 [1] => mysql
 [2] => взлом
 [1hr] => 10
 [1hr] => 10

… найден.

Спасибо за любую помощь,

Джеймс

Это идеальная работа для итераторов :

 $iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($array)); foreach($iterator as $key => $value) { echo "$key => $value\n"; } 

См. Введение в Итераторы SPL и Live Demo в кодексе

EDIT: альтернативой будет array_walk_recursive как показано в ответе Finbarr ниже

См. Array_walk_recursive – функция библиотеки PHP, которая рекурсивно вызывает определенную пользователем функцию по предоставленному массиву.

Из документов PHP:

 <?php $sweet = array('a' => 'apple', 'b' => 'banana'); $fruits = array('sweet' => $sweet, 'sour' => 'lemon'); function test_print($item, $key) { echo "$key holds $item\n"; } array_walk_recursive($fruits, 'test_print'); ?> 

Вывод:

 a holds apple b holds banana sour holds lemon 

Обратите внимание: Any key that holds an array will not be passed to the function. ,

EDIT: немного менее уродливый пример:

 <?php $sweet = array('a' => 'apple', 'b' => 'banana'); $fruits = array('sweet' => $sweet, 'sour' => 'lemon'); array_walk_recursive($fruits, function ($item, $key) { echo "$key holds $item\n"; }); ?> 

Как правило, в такой ситуации вам придется написать рекурсивную функцию, которая будет обрабатывать элемент, если это не массив; и называть себя элементом, если это массив.

Здесь у вас может быть что-то вроде этого:

 $arr = array( 'languages' => array( 'php', 'mysql', 'inglip', ), 'rates' => array( 'incall' => array('1hr' => 10), 'outcall' => array('1hr' => 10), ), ); function recurse($item) { foreach ($item as $key => $value) { if (is_array($value)) { recurse($value); } else { echo "$key : $value\n"; } } } 

И вызов этой рекурсивной функции в вашем массиве:

 recurse($arr); 

Вы получите:

 0 : php 1 : mysql 2 : inglip 1hr : 10 1hr : 10 

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

 function recursive_foreach($array, $callback) { foreach($array as $key => $value) { if (is_array($value)) { recursive_foreach($value, $callback); } else { call_user_func($callback, $key, $value); } } } 

Где $callback – это обратный вызов, принимающий два аргумента: ключ и значение. Например:

 recursive_foreach($array, function($k, $v) { echo "$k => $v<br>"; }); 
 function array_spelunk($array = array()) { foreach($array as $key => $node) { if (is_array($node)) { array_spelunk($node); } else { echo "[$key] [$node]\n"; } } } array_spelunk($your_nested_array); 

Я хочу вызвать функцию для каждого элемента массива. Это, очевидно, очень просто с foreach ()

Если вы хотите запустить функцию для каждого элемента глубокого массива, вы можете использовать array_walk_recursive ()

 array_walk_recursive($array, function($v, $k) { echo "$k => $v\n"; }); 

Если вы хотите перебирать каждый элемент с помощью foreach , вам нужен рекурсивный итератор, как упоминалось ранее.

Если вы не знаете, какой из них использовать, перейдите к foreach + рекурсивному итератору. Это легче понять для большинства людей.

 function recurse($element, $key = null) { if(is_array($element)) { foreach($element as $k => $v) { recurse($v, $k); } }else{ //Do what you want here. $element is value, $key is the key } } 
 function traverseArray($array) { foreach($array as $key=>$value) { if(is_array($value)) { traverseArray($value); }else{ echo '['.$key.']'.' => '.$value.'<br />\n'; } } } 
 function getEndNodes($input, $ret = array()) { foreach ($input as $key => $value) { if (!is_array($input[$key])) { $ret[$key] = $value; } else { $ret = getEndNodes($input[$key],$ret); } } return $ret; } // Usage: $endNodes = getEndNodes($yourarray);