Reputation: 43
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
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
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
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