Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free.

I would like to build a multidimensional array from an array. For example I would like

$test = array (
0 => 'Tree',
1 => 'Trunk',
2 => 'Branch',
3 => 'Limb',
4 => 'Apple',
5 => 'Seed'
);

to become

$test = 
array (
   'Tree' => array (
       'Trunk' => array (
           'Branch'  => array (
               'Limb'  => array (
                   'Apple'  => array (
                       'Seed' => array ()
                   )
               )
           )
       )
   )
);

or more simply

$result[Tree][Trunk][Branch][Limb][Apple][Seed] = null;

I'm trying to do this with a recursive function but i'm hitting memory limit so I'm clearly doing it wrong.

<?php
$test = array (
0 => 'Tree',
1 => 'Trunk',
2 => 'Branch',
3 => 'Limb',
4 => 'Apple',
5 => 'Seed'
);



print_r($test);





print "results of function";

print_r(buildArray($test));



function buildArray (&$array, &$build = null)
{
    if (count($array) > 0)
    {

        //create an array, pass the array to itself removing the first value



        $temp = array_values($array);   
        unset ($temp[0]);           
        $build[$array[0]] =  $temp;


        buildArray($build,$temp);



        return $build;
    }

    return $build;


}
share|improve this question
    
This is a good example of why recursion isn't necessarily a good idea most of the time. It is typically very easy to unwind recursion, and in doing so you get typically faster, less footprint, easier to understand code. –  John Cartwright May 15 at 18:48

4 Answers 4

up vote 2 down vote accepted

This function works recursively and does the trick:

function buildArray($from, $to = []) {  
    if (empty($from)) { return null; }
    $to[array_shift($from)] = buildArray($from, $to);
    return $to;
}

In your code I would expect you see an error. You are talking to $build in your first iteration as if it where an array, while you have defaulted it to null.

share|improve this answer

Here's an approach with foreach and without recursion, which works:

function buildArray($array)
{
    $new = array();
    $current = &$new;
    foreach($array as $key => $value)
    {
        $current[$value] = array();
        $current = &$current[$value];
    }
    return $new;
}

[ Demo ]

Now your function... first, using $build[$array[0]] without defining it as an array first produces an E_NOTICE. Second, your function is going into infinite recursion because you are not actually modifying $array ($temp isn't the same), so count($array) > 0 will be true for all of eternity.
And even if you were modifying $array, you couldn't use $array[0] anymore, because you unset that, and the indices don't just slide up. You would need array_shift for that.
After that, you pass $build and $temp to your function, which results in further because you now you assign $build to $temp, therefore creating another loop in your already-infinitely-recurring loop.

I was trying to fix all of the above in your code, but eventually realized that my code was now pretty much exactly the one from Pevara's answer, just with different variable names, so... that's that.

share|improve this answer

It seems to be easy

$res = array();
$i = count($test);
while ($i) 
    $res = array($test[--$i] => $res);
var_export($res);

return

array ( 'Tree' => array ( 'Trunk' => array ( 'Branch' => array ( 'Limb' => array ( 'Apple' => array ( 'Seed' => array ( ), ), ), ), ), ), )
share|improve this answer
    
Interesting solution to not use pointers. Not the most efficient though. –  John Cartwright May 15 at 18:46
    
@JohnCartwright Why is it less efficient than calling functions? –  splash58 May 15 at 18:49
    
It's nothing to do with functions. It's to do with creating copies vs references. –  John Cartwright May 15 at 19:04
    
@JohnCartwright You have written Not the most efficient though. What is not effective in my code? just wondering –  splash58 May 15 at 19:08
    
I didn't understand your last comment. –  John Cartwright May 15 at 19:09

Using a pointer, keep re-pointing it deeper. Your two output examples gave array() and null for the deepest value; this gives array() but if you want null, replace $p[$value] = array(); with $p[$value] = $test ? array() : null;

$test = array(
    'Tree',
    'Trunk',
    'Branch',
    'Limb',
    'Apple',
    'Seed'
);

$output = array();
$p = &$output;
while ($test) {
    $value = array_shift($test);
    $p[$value] = array();
    $p = &$p[$value];
}
print_r($output);
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.