Я хочу вызвать функцию для каждого элемента массива. Это очевидно очень легко с 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);