views:

776

answers:

4

Is it possible, in PHP, to flatten a (bi/multi)dimensional array without using recursion or references?

I'm only interested in the values so the keys can be ignored, I'm thinking in the lines of array_map() and array_values().

+2  A: 

This solution is non-recursive. Note that the order of the elements will be somewhat mixed.

function flatten($array) {
    $return = array();
    while(count($array)) {
        $value = array_shift($array);
        if(is_array($value))
            foreach($value as $sub)
                $array[] = $sub;
        else
            $return[] = $value;
    }
    return $return;
}
too much php
Clever idea, but there's a bug. "$array[] = $value" doesn't add all the *elements* of $value to $array, it merely add $value itself. If you run this code, it will loop indefinitely.
Todd Owen
Yes, `shifting` the value off the array and appending it again to the end doesn't make much sense. I guess you wanted to `array_merge()` instead?
deceze
+1 for answering the question. Recursion would be more fun, though.
nilamo
+1  A: 

Uses recursion. Hopefully upon seeing how not-complex it is, your fear of recursion will dissipate once you see how not-complex it is.

function flatten($array) {
    if (!is_array($array)) {
        // nothing to do if it's not an array
        return array($array);
    }

    $result = array();
    foreach ($array as $value) {
        // explode the sub-array, and add the parts
        $result = array_merge($result, flatten($value));
    }

    return $result;
}


$arr = array('foo', array('nobody', 'expects', array('another', 'level'), 'the', 'Spanish', 'Inquisition'), 'bar');
echo '<ul>';
foreach (flatten($arr) as $value) {
    echo '<li>', $value, '</li>';
}
echo '<ul>';

Output:

  • foo
  • nobody
  • expects
  • another
  • level
  • the
  • Spanish
  • Inquisition
  • bar
  • nilamo
    I don't fear recursion, I just want to learn other ways to do the same.
    Alix Axel
    +7  A: 

    As of PHP 5.3 the shortest solution seems to be array_walk_recursive() with the new closures syntax:

    function flatten(array $array) {
        $return = array();
        array_walk_recursive($array, function($a) use (&$return) { $return[] = $a; });
        return $return;
    }
    
    too much php
    That's a nice solution!
    Alix Axel
    +1  A: 

    You can use the Standard PHP Library (SPL) to "hide" the recursion.

    $a = array(1,2,array(3,4, array(5,6,7), 8), 9);
    $it = new RecursiveIteratorIterator(new RecursiveArrayIterator($a));
    foreach($it as $v) {
      echo $v, " ";
    }
    

    prints

    1 2 3 4 5 6 7 8 9
    
    VolkerK
    Am I the only one that thinks 'RecursiveIteratorIterator' is a silly name?
    nilamo
    It's more "logical" than "catchy". Not everything can have a fantastic name like JOGL, Knol or Azure :-)
    VolkerK