1

I am trying to find a way to create an array of directories. But as we all know directories can have many subDirs and those subDirs can have more subDir and so on and on. The directories length are unknown as it can change.

Say I have a directory as www/webs/apps/pics and another www/webs/test.

The idea would be to have an array such as: (yes the below is json, i just converted it in my php demonstration because i find it easier to read)

{
  "www": {
     "webs": {
         "apps": {
            "pics": "Im Here"
             }
         },
       "test": "im Here too"
     }
}

There is no relation from the above output to the below code. The below code is here just to give an idea what I need.

$exploedDir = explode("/", $unsortedDir);
foreach ($exploedDir as $dir){
    $this->allDirectiroesFound[$dir] = $dir;
}

How can I make $this->allDirectiroesFound has as many dimensions as it is needed without knowing the length of the directory, I cant hard code $this->allDirectiroesFound[][][][][][] it as next time around the array length might be [][][].

atymic
  • 3,093
  • 1
  • 13
  • 26
LukeDS
  • 141
  • 8
  • 2
    Usually once you start to want more than "just arrays", it's time to pick a better datastructure. In this case, what you really want is a tree, not "an array of arrays of arrays of arrays of ..." – Mike 'Pomax' Kamermans Aug 12 '19 at 22:37
  • 1
    I think the question I linked should handle this perfectly for you. Here's a working example with your example paths: https://3v4l.org/PEBrL – Don't Panic Aug 12 '19 at 23:17
  • @Don'tPanic thanks – LukeDS Aug 13 '19 at 18:34
  • @Don'tPanic could explain the pass by reference bit? why does the second ```foreach``` loop needs this temp as pass by reference ```&$temp[$key];```? thanks – LukeDS Aug 13 '19 at 20:58
  • Normally PHP will pass everything by value. If you assign `$temp = $temp[$key];` without the reference, then `$temp` just takes the _value_ of `$temp[$key]`, which is `null` because it hasn't been set to any value yet. With the reference assignment, `$temp` points to `$temp[$key]` instead of taking its value so you're able to continue to add nested keys. – Don't Panic Aug 13 '19 at 21:23

2 Answers2

1

You can just reverse each of the path arrays and then go on creating the Keys from the last directory.

$paths = [
    'www/webs/apps/pics',
    'www/webs/test',
];

$finalArray = [];
foreach($paths as $path){
    $revArr = array_reverse(explode("/", $path)); // This is the trick. Start to build from inside out.
    $pathArray = [];
    foreach($revArr as $key){
            $tempBucket = $pathArray;
            $pathArray = []; // Create fresh empty array to hold the 
            $pathArray[$key] = $tempBucket;
    }

    $finalArray = array_merge_recursive($pathArray, $finalArray); // Recursively Merge the array into the main array
}

echo "<pre>";
print_r(json_encode($finalArray, JSON_PRETTY_PRINT));
echo "</pre>";

DEMO

Mohd Abdul Mujib
  • 13,071
  • 8
  • 64
  • 88
  • 1
    Thanks this is a good way of doing I never used ```array_reverse``` before so its something nice to learn :) – LukeDS Aug 13 '19 at 21:00
  • Indeed it is, then there are more optimal solutions as suggested by the community which this questions is a duplicate of. I just wrote this code off the top of my head in 5 mins :) I myself learned a new thing in this endeavour, viz. Accessing a non existent array key **by reference** will create it!! Like Wow!!! I guess, everyone's learning new things here. – Mohd Abdul Mujib Aug 13 '19 at 21:50
0

I guess you would need to use arrays of arrays to solve this.

e.g.

var directories = ["base"];
var subdir1 = ["subdir1"];
var subsubdir1 = ["subsubdir1"];
var subsubdir1 = ["subsubdir2"];

subdir.push(subsubdir1);
subdir.push(subsubdir2);
directories.push(subdir1);

so this forms a base->subdir1->[subsubdir1, subsubdir2] structure. The complication comes in ensuring that every 'push' you perform is an array to allow adjacent siblings to exist for that particular sub-directory. That and keeping track of the directory structure

schlock
  • 519
  • 3
  • 5
  • 14