PHP中使用foreach()遍历多维数组的方法?

15
我想在数组中的每个元素上调用一个函数。如果是一个简单的数组,使用foreach()很容易,但当数组包含其他数组时会很复杂。有没有人能帮我写一个函数,可以对多层嵌套数组中的每个键值对执行一些代码。理论上可以无限嵌套,但如果递归方法行不通,就需要设置一个好的限制,比如3个迭代(数组嵌套数组嵌套数组)。
下面是一个示例数组,来自于$_POST:
Array
(
    [languages] => Array
    (
        [0] => php
        [1] => mysql
        [2] => inglip
    )
[rates] => Array ( [incall] => Array ( [1hr] => 10 )
[outcall] => Array ( [1hr] => 10 )
) )
请注意,我想运行一个代码片段(一个函数),该函数将传递数组结构中的每个“末节点”,因此在上面的示例中,当发现以下内容时将调用它:
[0] => php
[1] => mysql
[2] => inglip
[1hr] => 10
[1hr] => 10
谢谢任何帮助, James

6
(附注)“终节点”的正确术语是叶子节点。 - Gordon
请参阅在一个数组中获取所有值。虽然不是严格的重复,但高度相关。 - Gordon
1
还要看一下 bool array_walk_recursive( ... ) => http://php.net/manual/en/function.array-walk-recursive.php - jave.web
9个回答

25

11

参见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

注意,任何包含数组的键将不会被传递到函数中。

编辑:稍微好看一点的示例:


<?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";
});
?>

1
除了我的答案之外,这是解决问题的唯一实用方法。所有那些用户递归函数都太荒谬了。你可能想要添加一个小的使用示例来说明用法。 - Gordon
1
@Jam array_walk_recursive非常适合“在数组中的每个元素上调用一个函数”,但好吧,我不会抱怨已经被接受的答案 :) 我会编辑我的答案并在这里包含一个链接。谢谢! - Gordon
1
这边没有任何抱怨。两个答案都完全有效。解决同一问题的方法有很多种,而程序员可以选择适合自己的方式。 - Finbarr
我对这个答案唯一的小问题是必须将函数名称作为字符串引用。对我来说,使用RecursiveIterator函数更加清晰。 - Bojangles
好的,就像所有设计为回调的PHP库函数一样,您可以直接将匿名函数传递给array_walk_recursive - 您不需要使用函数名称作为字符串。 - Finbarr

6

通常,在这种情况下,您需要编写一个递归函数--如果它不是数组,则处理一个项目; 如果它是一个数组,则调用自身。


在这里,您可以像这样拥有:

$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

3

这里是一个简单的可重复使用的实现:

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是一个接受两个参数key和value的回调函数。例如:

recursive_foreach($array, function($k, $v) {
    echo "$k => $v<br>";
});

不知道PHP支持匿名函数! - Finbarr
2
@Finbarr @Jon 在 PHP 5.3 之前也支持匿名函数,只是使用起来很麻烦且速度较慢,需要使用 create_function 函数。 - Gordon

1
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);

1
我想在数组的每个元素上调用一个函数。使用foreach()很容易实现这一点。
如果您想在深层数组的每个元素上运行函数,可以使用array_walk_recursive()
array_walk_recursive($array, function($v, $k)
{  
    echo "$k => $v\n";
});

如果您想使用foreach迭代每个元素,则需要一个递归迭代器,如先前所述。

如果您不确定要使用哪个,请选择foreach + 递归迭代器。对于大多数人来说,这更容易理解。


0
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);

0
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
  } 
}

0
function traverseArray($array)
{ 
    foreach($array as $key=>$value)
    { 
        if(is_array($value))
        { 
            traverseArray($value); 
        }else{
            echo '['.$key.']'.' => '.$value.'<br />\n'; 
        } 
    }
}

1
是的,这是我想到的第一件事情。感谢你付出了努力发布回答,但这显然并不是一个理想的解决方案。 - Bojangles

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接