Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert single array to multidimensional array in php

If a problem i try to solve now some hours, but simply cant find a solution.

If a single array of paths

$singleArray = array(
   '/Web',
   '/Web/Test1',
   '/Web/Test2', 
   '/Web/Test2/Subfolder',
   '/Web/Test3',
   '/Public'
);

From that array i want to create a mulitdimensional array, which keeps the keys but put subfolders in the correct parent folders. Later i want to loop over the new array to create a folder tree (but thats not a problem)

The new array should look like this:

$multiArray = array(
   '/Web'=>array(
      '/Web/Test1'=>array(),
      '/Web/Test2'=>array(
          '/Web/Test2/Subfolder'=>array()
      ),
      '/Web/Test3'=>array()
   ),
   '/Public'=>array()
);
like image 861
devops21212 Avatar asked Jul 06 '15 15:07

devops21212


Video Answer


2 Answers

The code below will make the array you want. The key to solve your problem is to create a reference to the array every iteration.

<?php
$singleArray = array(
    '/Web',
    '/Web/Test1',
    '/Web/Test2',
    '/Web/Test2/Subfolder',
    '/Web/Test3',
    '/Public'
);

$multiArray = array();

foreach ($singleArray as $path) {
    $parts       = explode('/', trim($path, '/'));
    $section     = &$multiArray;
    $sectionName = '';

    foreach ($parts as $part) {
        $sectionName .= '/' . $part;

        if (array_key_exists($sectionName, $section) === false) {
            $section[$sectionName] = array();
        }

        $section = &$section[$sectionName];
    }
}
like image 146
Jesper Avatar answered Sep 30 '22 10:09

Jesper


Got this working! Great challenge!

First I sort the array by number of folders, so that the first to be processed are those with fewest folders (in the root).

Then the function iterates through each of the array items and each folder in that item, comparing it to the existing items in the array and, if it exists, placing it inside of that item as a multidimensional array.

This will work for up to two subfolders - /root/sub1/sub2 - but it's quite straightforward so simple to add functionality for deeper use.

This sample code also prints out the before/after arrays:

$singleArray = array(
   '/Web',
   '/Web/Test1',
   '/Web/Test2', 
   '/Web/Test2/Subfolder',
   '/Web/Test3',
   '/Public'
);


echo "<pre>";
print_r($singleArray);

$multiArray = array();


//first sort array by how many folders there are so that root folders are processed first
usort($singleArray, function($a, $b) {

    $a_folders = explode("/", $a);
    $b_folders = explode("/", $b);

    $a_num = count($a_folders); //number of folders in first
    $b_num = count($b_folders); //number of folders in second

    if($a_num > $b_num) return -1;
    elseif($a_num < $b_num) return 1;
    else return 0;

});

//foreach in array
foreach($singleArray as $item){

    //get names of folders
    $folders = explode("/", $item);

    //if the first folder exists
    if(in_array($folders[0], $multiArray)){

        $key1 = array_search($folders[0], $multiArray);

        //repeat for subfolder #1
        if(in_array($folders[1], $multiArray[$key1])){

            $key2 = array_search($folders[1], $multiArray[$key1]);

            //repeat for subfolder #2
            if(in_array($folders[2], $multiArray[$key1][$key2])){

                $key3 = array_search($folders[2], $multiArray[$key1][$key2]);

                array_push($multiArray[$key1][$key2][$key3], $item);

            } else array_push($multiArray[$key1][$key2], $item);

        } else array_push($multiArray[$key1], $item);

    } else array_push($multiArray, $item);

}

//reverse the array so that it looks nice
$multiArray = array_reverse($multiArray);

print_r($multiArray);

This will output:

Array
(
    [0] => /Web
    [1] => /Web/Test1
    [2] => /Web/Test2
    [3] => /Web/Test2/Subfolder
    [4] => /Web/Test3
    [5] => /Public
)
Array
(
    [0] => /Web
    [1] => /Public
    [2] => /Web/Test1
    [3] => /Web/Test2
    [4] => /Web/Test3
    [5] => /Web/Test2/Subfolder
)
like image 32
Ben Avatar answered Sep 30 '22 11:09

Ben