2

Possible Duplicate:
String with array structure to Array

I have an array as such

$foo = array();
$foo['/'] = 'value';
$foo['/foo'] = 'value';
$foo['/foo/bar'] = 'value';
$foo['/test'] = 'value';
$foo['/test/tester'] = 'value';
$foo['/hello'] = 'value';
$foo['/hello/world'] = 'value';
$foo['/hello/world/blah'] = 'value';

What I need to do is store these sub-pages in a tree-like structure, so instead it needs to be automatically converted to:

   $foo = array(
    '/' => array(
        'value' => 'value',
        'children' => array(
            '/foo' => array(
                'value' => 'value',
                'children' => array(
                    '/foo/bar' => array(
                        'value' => 'value',
                        'children' => array()
    );

What I figured I would be doing, is something like:

$newArray = array();
foreach( $foo as $key => $val )
{
    $bits = explode('/', $key);

    foreach( $bits as $bit )
    {
        $newArray[$bit] = array('val' => $val);
    }
}

print_r($newArray);

Except I somehow need to go into the newArray, and keep track of how deep I am into the array. Does anyone have an example script of how they have done so, or have any funky array walk tips to do so?

Community
  • 1
  • 1

1 Answers1

3

The solution can be achieved with variable references (aka "pointers"), for more information see http://php.net/manual/en/language.references.php

<?php

$foo = array();
$foo['/'] = 'value';
$foo['/foo'] = 'value';
$foo['/foo/bar'] = 'value';
$foo['/test'] = 'value';
$foo['/test/tester'] = 'value';
$foo['/hello'] = 'value';
$foo['/hello/world'] = 'value';
$foo['/hello/world/blah'] = 'value';

function nest(&$foo)
{
    $new = array();
    foreach ($foo as $path => $value)
    {
        $pointer =& $new;
        $currentPath = '';
        if ($pathParts = explode('/', trim($path, '/'))) {
            while($nextKey = array_shift($pathParts)) {
                $currentPath .= '/' . $nextKey;
                if (!isset($pointer['children'][$currentPath])) {
                    $pointer['children'][$currentPath] = array();
                }
                $pointer =& $pointer['children'][$currentPath];
            }
        }
        $pointer['value'] = $value;
    }
    return $new ? array('/' => $new) : array();
}

print_r($foo);
print_r(nest($foo));

?>
jchook
  • 5,317
  • 2
  • 31
  • 37
  • Note that this example is called "iterative" because it does not use recursion. I'm not sure what a recursive version would look like but I invite @blockhead or someone else to try :-) – jchook Jun 14 '12 at 19:30