在PHP中提取多维数组的叶节点

时间:2009-07-25 09:14:32

标签: php arrays

假设我在PHP中有一个看起来像这样的数组

array
(
   array(0)
   (
       array(0)
       (
         .
         . 
         .
       )

       .
       .
       array(10)
       (
         ..
       )
   )

   .
   . 
   .
   array(n)
   (

     array(0)
     (
     )
   )
 )

我需要将这个多维数组的所有叶子元素都放到一个线性数组中,如何在不使用递归的情况下这样做呢?

 function getChild($element)
 {

     foreach($element as $e)
     {

       if (is_array($e)
       {
          getChild($e);
       }
     }
 }

注意:上面的代码片段,可怕的未完成

更新:数组的例子

Array
(
    [0] => Array
        (
            [0] => Array
                (
                    [0] => Seller Object
                        (
                            [credits:private] => 5000000
                            [balance:private] => 4998970
                            [queueid:private] => 0
                            [sellerid:private] => 2
                            [dateTime:private] => 2009-07-25 17:53:10
                        )

                )

        )

...剪断。

[2] => Array
    (
        [0] => Array
            (
                [0] => Seller Object
                    (
                        [credits:private] => 10000000
                        [balance:private] => 9997940
                        [queueid:private] => 135
                        [sellerid:private] => 234
                        [dateTime:private] => 2009-07-14 23:36:00
                    )

            )

    ....snipped....

    )

6 个答案:

答案 0 :(得分:11)

实际上,有一个功能可以解决问题,请查看手册页:http://php.net/manual/en/function.array-walk-recursive.php

从页面改编的快速片段:

$data = array('test' => array('deeper' => array('last' => 'foo'), 'bar'), 'baz');

var_dump($data);

function printValue($value, $key, $userData) 
{
    //echo "$value\n";
    $userData[] = $value;
}


$result = new ArrayObject();
array_walk_recursive($data, 'printValue', $result);

var_dump($result);

答案 1 :(得分:6)

您可以使用迭代器,例如:

$result = array();
foreach(new RecursiveIteratorIterator(new RecursiveArrayIterator($array), RecursiveIteratorIterator::LEAVES_ONLY) as $value) {
    $result[] = $value;
} 

答案 2 :(得分:2)

试试这个:

function getLeafs($element) {
    $leafs = array();
    foreach ($element as $e) {
        if (is_array($e)) {
            $leafs = array_merge($leafs, getLeafs($e));
        } else {
            $leafs[] = $e;
        }
    }
    return $leafs;
}

编辑显然您不需要递归解决方案。所以这是一个使用堆栈的迭代解决方案:

function getLeafs($element) {
    $stack = array($element);
    $leafs = array();
    while ($item = array_pop($stack)) {
        while ($e = array_shift($item)) {
            if (is_array($e)) {
                array_push($stack, array($item));
                array_push($stack, $e);
                break;
            } else {
                $leafs[] = $e;
            }
        }
    }
    return $leafs;
}

答案 3 :(得分:2)

使用堆栈:

<?php

$data = array(array(array("foo"),"bar"),"baz");

$results = array();
$process = $data;
while (count($process) > 0) {
    $current = array_pop($process);
    if (is_array($current)) {
        // Using a loop for clarity. You could use array_merge() here.
        foreach ($current as $item) {
            // As an optimization you could add "flat" items directly to the results array here.
            array_push($process, $item);
        }
    } else {
        array_push($results, $current);
    }
}

print_r($results);

输出:

Array
(
    [0] => baz
    [1] => bar
    [2] => foo
)

这应该比递归方法更有效。尽管我们在这里进行了大量的数组操作,但PHP具有写时复制语义,因此实际数据的实际zval不会在内存中重复。

答案 4 :(得分:1)

没有展平功能直接获得叶子。如果有更多的数组子项,只有当你到达底部将元素移动到结果平面数组时,你必须使用递归来检查每个数组。

答案 5 :(得分:1)

刚刚遇到同样的问题并使用了另一种未提及的方法。接受的答案要求ArrayObject class正常工作。可以使用array原语和anonymous function中的use关键字(PHP&gt; = 5.3)来完成:

<?php
$data = array(
    array(1,2,3,4,5),
    array(6,7,8,9,0),
);
$result = array();
array_walk_recursive($data, function($v) use (&$result) { # by reference
    $result[] = $v;
});
var_dump($result);