Extract leaf nodes of multi-dimensional array in P

2020-03-30 03:28发布

问题:

Suppose I have an array in PHP that looks like this

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

       .
       .
       array(10)
       (
         ..
       )
   )

   .
   . 
   .
   array(n)
   (

     array(0)
     (
     )
   )
 )

And I need all the leaf elements of this mulit-dimensional array into a linear array, how should I go about doing this without resorting recursion, such like this?

 function getChild($element)
 {

     foreach($element as $e)
     {

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

Note: code snippet above, horribly incompleted

Update: example of array

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
                        )

                )

        )

...snipped.

[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....

    )

)

回答1:

Actually, there is a single function that will do the trick, check the manual page at: http://php.net/manual/en/function.array-walk-recursive.php

Quick snippet adapted from the page:

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


回答2:

You could use iterators, for example:

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


回答3:

Use a stack:

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

Output:

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

This should be more memory efficient than the recursive approach. Despite the fact that we do a lot of array manipulation here, PHP has copy-on-write semantics so the actual zvals of the real data won't be duplicated in memory.



回答4:

Try this:

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

Edit   Apparently you don’t want a recursive solution. So here’s an iterative solution that uses a stack:

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


回答5:

There is no flatten function to get directly the leafs. You have to use recursion to check for each array if has more array children and only when you get to the bottom to move the element to a result flat array.



回答6:

Just got the same issue and used another method that was not mentioned. The accepted answer require the ArrayObject class to work properly. It can be done with the array primitive and the use keyword in the anonymous function (PHP >= 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);


标签: php arrays