0

I have an array of arrays containing filepaths

Array
(
    [0] => Array
        (
            [0] => cat/file1.php
        )

    [1] => Array
        (
            [0] => dog/file2.php
        )
    [2] => Array
        (
            [0] => cow/file3.php
        )
    [3] => Array
        (
            [0] => cow/file4.php
        )
    [4] => Array
        (
            [0] => dog/bowl/file5.php
        )

)

and need to convert it into a single multi-dimensional array holding the file names based on those file paths i.e.

Array
(
    [cat] => Array
        (
            [0] => file1.php
        )

    [dog] => Array
        (
            [0] => file2.php
            [bowl] => Array
                (
                     [0] => file5.php
                )

        )
    [cow] => Array
        (
            [0] => file3.php
            [1] => file4.php
        )

)

I have been experimenting with exploding the string and using for/foreach loops to build up an array non-recursively/recursively but have been unsuccessful so far

1
  • 1
    Can provide your code you have tried so far, which does not work? Commented Sep 28, 2016 at 11:15

1 Answer 1

2

Yep, it can be confusing when iterating through associative arrays, especially if there's folder structure encoded in array values. But without fear and using references, one can manage. Here's a working snippet:

$array = [
    ['cat/file1.php'],
    ['dog/file2.php'],
    ['cow/file3.php'],
    ['cow/file4.php'],
    ['dog/bowl/file5.php'],
    ['dog/bowl/file6.php'],
    ['dog/bowl/soup/tomato/file7.php']
];

$result = [];
foreach ($array as $subArray)
{
    foreach ($subArray as $filePath)
    {
        $folders = explode('/', $filePath);
        $fileName = array_pop($folders); // The last part is always the filename

        $currentNode = &$result; // referencing by pointer
        foreach ($folders as $folder)
        {
            if (!isset($currentNode[$folder]))
                $currentNode[$folder] = [];

            $currentNode = &$currentNode[$folder]; // referencing by pointer
        }
        $currentNode[] = $fileName;
    }
}
var_dump($result);

The result is the following:

array(3) {
  'cat' =>
  array(1) {
    [0] =>
    string(9) "file1.php"
  }
  'dog' =>
  array(2) {
    [0] =>
    string(9) "file2.php"
    'bowl' =>
    array(3) {
      [0] =>
      string(9) "file5.php"
      [1] =>
      string(9) "file6.php"
      'soup' =>
      array(1) {
        'tomato' =>
        array(1) {
          [0] =>
          string(9) "file7.php"
        }
      }
    }
  }
  'cow' =>
  array(2) {
    [0] =>
    string(9) "file3.php"
    [1] =>
    string(9) "file4.php"
  }
}

...which, I guess, is what you wanted.

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

1 Comment

perfect, thanks! Did not think about using references

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.