6

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;


}
1
  • 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. Commented May 15, 2015 at 18:48

4 Answers 4

8

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.

Sign up to request clarification or add additional context in comments.

Comments

2

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.

Comments

2

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 ( ), ), ), ), ), ), )

7 Comments

Interesting solution to not use pointers. Not the most efficient though.
@JohnCartwright Why is it less efficient than calling functions?
It's nothing to do with functions. It's to do with creating copies vs references.
@JohnCartwright You have written Not the most efficient though. What is not effective in my code? just wondering
I didn't understand your last comment.
|
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.