0

So I've got a list of paths, such as:

path/to/directory/file1
path/directory/file2
path2/dir/file3
path2/dir/file4

And I'd like to convert them into a multidimensional array like this:

array(
  path => array(
    to => array(
      directory => array(
        file1 => someValue
      ),
    ),
    directory => array(
      file2 => someValue
    ),
  ),
  path2 => array(
    dir => array(
      file3 => someValue,
      file4 => someValue
    )
  )
)

My first thought was to explode() the paths into segments and set up the array using a foreach loop, something like this:

$arr = array();
foreach ( $path as $p ) {
    $segments = explode('/', $p);
    $str = '';
    foreach ( $segments as $s ) {
        $str .= "[$s]";
    }
    $arr{$str} = $someValue;
}

But this doesn't work, and since the number of segments varies, I've kinda got stumped. Is there away to do this?

1

4 Answers 4

1

If somevalue can be an empty array:

<?php
$result = array();

$input = [
    'path/to/directory/file1',
    'path/directory/file2',
    'path2/dir/file3',
    'path2/dir/file4',
];

foreach( $input as $e ) {
    nest( $result, explode('/', $e));
}

var_export($result);


function nest(array &$target, array $parts) {
    if ( empty($parts) ) {
        return;
    }
    else {
        $e = array_shift($parts);
        if ( !isset($target[$e]) ) {
            $target[$e] = [];
        }
        nest($target[$e], $parts);
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! I adapted your example to come up with the answer I needed!
0

Here is the solution and a easy way
Just Reverse the whole exploded array and start creating array within a Array

$path[1] = "path/to/directory/file1";
$path[2] = "path/directory/file2";
$path[3] = "path2/dir/file3";
$path[4] = "path2/dir/file4";
$arr = array();
$b = array();
$k = 0;
foreach($path as $p) {

$c = 0;
$segments = explode('/', $p);
$reversed = array_reverse($segments);
foreach($reversed as $s) {
if ($c == 0) {
  $g[$k] = array($s => "somevalue");

} else {

  $g[$k] = array($s => $g[$k]);
}

$c++;
}
$k++;

}
var_dump($g);

2 Comments

Thanks! But it's not quite what I was looking for. It places each sub-array in an integer-indexed array and it doesn't group files from the same path together.
yes i agree it is adding sub-array but if you print_r($g) you will find all file path being together
0

Thanks so much VolkerK! Your answer didn't quite answer my question but it got me on the right track. Here's the version I ended up using to get it to work:

$result = array();

$input = [
    'path/to/directory/file1' => 'someValue',
    'path/directory/file2' => 'someValue',
    'path2/dir/file3' => 'someValue',
    'path2/dir/file4' => 'someValue',
];

foreach( $input as $e=>$val ) {
    nest( $result, explode('/', $e), $val);
}

var_export($result);

function nest(array &$target, array $parts, $leafValue) {

    $e = array_shift($parts);

    if ( empty($parts) ) {
        $target[$e] = $leafValue;
        return;
    }

    if ( !isset($target[$e]) ) {
        $target[$e] = [];
    }

    nest($target[$e], $parts, $leafValue);
}

I basically just added the somevalue as $leafValue and moved the base case around so that it would add the leafValue instead of a blank array at the end.

This results in:

Array
(
    [path] => Array
        (
            [to] => Array
                (
                    [directory] => Array
                        (
                            [file1] => someValue
                        )
                )
            [directory] => Array
                (
                    [file2] => someValue
                )
        )
    [path2] => Array
        (
            [dir] => Array
                (
                    [file3] => someValue
                    [file4] => someValue
                )
        )
)

Thanks a lot!

Comments

0

It can be done without recursion

$path = array(
'path/to/directory/file1',
'path/directory/file2',
'path2/dir/file3',
'path2/dir/file4');

$arr = [];
$someValue = 'someValue';

foreach ( $path as $p ) {
    $segments = explode('/', $p);
    $str = '';
    $p = &$arr;
    foreach ( $segments as $s ) {
        if (! isset($p[$s] ) ) $p[$s] = array();
        $p = &$p[$s];
    }
    $p = $someValue;
}

print_r($arr);

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.