sunnysk32
sunnysk32

Reputation: 43

PHP Multidimensional Array to Flat Folder View

I have a multidimensional array like this one in PHP:

Array
(
    [folder1] => Array
        (
            [folder11] => Array
                (
                    [0] => index.html
                    [1] => tester.html
                )

            [folder12] => Array
                (
                    [folder21] => Array
                        (
                            [0] => astonmartindbs.jpg
                        )

                )

        )

)

and should be converted to a "file path" string like this one:

Array
(
    [0] => 'folder1/folder11/index.html'
    [1] => 'folder1/folder11/tester.html'
    [2] => 'folder1/folder12/folder21/astonmartindbs.jpg'
)

Has anybody any ideas?

I have tried a lot any all deleted... This is the starting point of my last try:

public function processArray( $_array ) {
foreach( $_array AS $key => $value ) {
    if( is_int( $key ) ) {

    } else {
    if( is_array( $value ) ) {
        $this->processArray( $value );
    } else {

    }
    }
}
echo $this->string;

}

But i do not come to an end.... Hope somebody can help?

Upvotes: 4

Views: 423

Answers (3)

hek2mgl
hek2mgl

Reputation: 157947

A recursive function may be what you are searching for. The following function will work:

/**
 * Flattens the array from the question
 *
 * @param array  $a       Array or sub array of directory tree
 * @param string $prefix  Path prefix of $a
 */
function flatten($a, $prefix = './') {
    $paths = array();
    foreach($a as $index => $item) {
        // if item is a string then it is a file name (or a leaf in tree)
        // prefix it and add it to paths
        if(is_string($item)) {
            $paths []= $prefix . $item;
        } else {
            // if item is a directory we call flatten on it again.
            // also we append the new folder name to $prefix
            foreach(flatten($item, $prefix . $index . '/') as $path) {
                $paths []= $path;
            }
        }         
    }
    return $paths;
}

var_dump(flatten($a));

Note that flatten() call itself inside the foreach loop with a sub array as argument. This is called a 'recursive algorithm'.

Upvotes: 5

dan-lee
dan-lee

Reputation: 14492

If you like the SPL you can use RecursiveArrayIterator and RecursiveIteratorIterator to iterate over a flat structure.

My result would look like this:

$arr = array(); // your array
$arr = new RecursiveArrayIterator($arr);
$iterator = new RecursiveIteratorIterator($arr, RecursiveIteratorIterator::SELF_FIRST);


$currentDepth = 0;
$currentPath = array();
$result = array();

foreach($iterator as $key => $value) {
  // if depth is decreased
  if ($iterator->getDepth() < $currentDepth) {
    // pop out path values
    do {
      $currentDepth--;
      array_pop($currentPath);
    } while($iterator->getDepth() < $currentDepth);
  }

  if (is_array($value)) {
    // add parent to the path
    $currentPath[] = $key;
    $currentDepth++;
  } else {
    // add children to result array
    $result[] = implode('/', $currentPath).'/'.$value;
  }
}

Dumping the data would then look like this:

print_r($result);
/*
Array
(
    [0] => folder1/folder11/index.html
    [1] => folder1/folder11/tester.html
    [2] => folder1/folder12/folder21/astonmartindbs.jpg
)
*/

Upvotes: 2

Akram El Hamdaoui
Akram El Hamdaoui

Reputation: 133

In your case, you need to implement, a recursive function, that you tried to do, here is a simple code, it may help you, i am not sure if that is working or no:

$result = array();
$d = 0;
$tmp = "";
public function processArray( $_array ,$before) {
foreach( $_array AS $key => $value ) {
    if( is_int( $key ) ) {  // If the key is a number, then there is no a sub-array 
      $result[$d] = $before . '/' . $value;
       $d++;
      $before="";
    } else {
    if( is_array( $value ) ) { // if the value is an array, then we will add the key into string that we will return and search into subarray.
 $before = $before . '/' . $key;
        $this->processArray( $value,$before  );
    } else {


    }
    }
}
return $result;

}

Upvotes: 0

Related Questions