PHP foreach() with arrays within arrays?
I want to call a function on each element in an array. This is obviously very easy with a for开发者_运维问答each()
, but where I start breaking down is when arrays contain arrays. Can someone help me out with a function that will execute some code for every key -> value pair from a set of arrays within arrays. The depth could, in theory, be infinite, but a good limit would be 3 iterations (array in array in array) if recursion couldn't work.
An example array would be one taken from $_POST below:
Array ( [languages] => Array ( [0] => php [1] => mysql [2] => inglip ) [rates] => Array ( [incall] => Array ( [1hr] => 10 ) [outcall] => Array ( [1hr] => 10 ) ) )
Just to make sure, what I want to do is run a piece of code (a function) that is passed every 'end node' in the array structure, so in the example above, it would be called when...
[0] => php [1] => mysql [2] => inglip [1hr] => 10 [1hr] => 10
... is found.
Thanks for any help,
James
That's a perfect job for Iterators:
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
foreach($iterator as $key => $value) {
echo "$key => $value\n";
}
See Introduction to SPL Iterators and Live Demo on codepad
EDIT: the alternative would be array_walk_recursive
as show in Finbarr's answer below
See array_walk_recursive - a PHP library function that recursively calls a user defined function against a provided array.
From PHP docs:
<?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');
?>
Output:
a holds apple
b holds banana
sour holds lemon
Note that Any key that holds an array will not be passed to the function.
.
EDIT: slightly less ugly example:
<?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";
});
?>
Typically, in this kind of situation, you'll have to write a recursive function -- which will deal with an item if it's not an array ; and call itself on an item if it's an array.
Here, you could have something like this :
$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";
}
}
}
And calling this recursive function on your array :
recurse($arr);
Would get you :
0 : php
1 : mysql
2 : inglip
1hr : 10
1hr : 10
Here's a simple reusable implementation:
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);
}
}
}
Where $callback
is a callback accepting two arguments: key and value. For example:
recursive_foreach($array, function($k, $v) {
echo "$k => $v<br>";
});
I want to call a function on each element in an array. This is obviously very easy with a foreach()
If you want to run a function on every element of a deep array, you can use array_walk_recursive()
array_walk_recursive($array, function($v, $k)
{
echo "$k => $v\n";
});
If you want to iterate over each element with foreach
, you need a recursive iterator as mentionned previously.
If you're not sure which one to use, go with foreach
+ recursive iterator. It's easier to grasp for most people.
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);
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);
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';
}
}
}
精彩评论