Simone Nigro
Simone Nigro

Reputation: 4887

PHP transform associative array of string in tree structure

I have a list of path (just strings), like this:

$data = array(
    array('path' => 'foo/bar/baz'),
    array('path' => 'foo/bar/baz/qux'),
    array('path' => 'foo/bar'),
    array('path' => 'bar/baz/foo'),
    array('path' => 'baz'),
);

I would like to achieve a structure like this

Array
(
    [foo] => Array
        (
            [bar] => Array
                (
                    [baz] => Array
                        (
                            [qux] => null
                        )
                )
        )
    [bar] => Array
        (
            [baz] => Array
                (
                    [foo] => null
                )
        )
    [baz] => null
)

Side note

  1. the structure displays only, non-common portions
  2. the leaf would be null (null for me would be without children)

I know you will ask me what have you tried? the problem is: I don't know how to deal the problem in the right way

can you give me some advice, without massacre of downvote?

Upvotes: 0

Views: 316

Answers (2)

Isaac
Isaac

Reputation: 11805

I got pretty close, but instead of the endings being null, they're array's with size 0.

<?php

function ProcessPath($entry,$depth,&$current)
{
  if($depth<count($entry))
  {
    $key = $entry[$depth];
    if(!isset($current[$key]))$current[$key] = null;
    ProcessPath($entry,$depth+1,$current[$key]);
  }
}


$data = array(
  array('path' => 'foo/bar/baz'),
  array('path' => 'foo/bar/baz/qux'),
  array('path' => 'foo/bar'),
  array('path' => 'bar/baz/foo'),
  array('path' => 'baz'),
);
$result = null;
foreach($data as $path)
{
  ProcessPath(explode("/",$path['path']),0,$result);
}

print_r($result);

?>

output

Array
(
    [foo] => Array
        (
            [bar] => Array
                (
                    [baz] => Array
                        (
                            [qux] => 
                        )

                )

        )

    [bar] => Array
        (
            [baz] => Array
                (
                    [foo] => 
                )

        )

    [baz] => 
)

Essentially the function ProcessPath takes:

  • An array of the split path
  • The current depth eg: [foo] (0) or foo > [bar] (1) or foo > bar > [baz] (2)
  • A reference to where on the array the path is being put (denoted by &$reference

First off the function checks if the depth is within the current path being processed.

Then it extracts the $key to simplify the rest of the code.

This is where the magic happens, if the output hasn't got the current path segment set, it sets it.

The last line recurses onto the next element in the path $entry by taking the same $entry, increasing the $depth by 1, and changing the $current to the new section $current[$key].

Upvotes: 2

Caleb Lewis
Caleb Lewis

Reputation: 543

What you could do is iterate over the paths, explode the string of each path, and then add each value to the new array depending on the position of the value. If the value is the first, then it'll be the base. If it's the 2nd, then it goes in as a new array inside the first one, and so on.

Upvotes: 0

Related Questions