4

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?

3 Answers 3

5

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'.

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

2 Comments

Your try doesn't looks so bad. Seems that you just needed the final trick ;)
Yeah i think so! But after about 2 hours of trying, i was totally confused.
2

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
)
*/

1 Comment

Thank you also! It works like charm, but i prefer @hek2mgl answer!
0

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;

}

1 Comment

Thank you also. But i have chosen @hek2mgl answer.

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.