Is it possible to count the number of dimensions in an array?
I want to be able to know the level of an array as it is being built.
The code loops through a bunch of directories to create a massive multi-dimensional array.
As the array is being created, I want to know how deep in the array I am.
1 2 3 4
---------------------
Root
A
A2
A3
A4
A4a
B
B2
B3
C
D
E
E2
E2a
E3
In the example above, the root directory is in level 1. All single uppercase letters are in level 2. All uppercase letters with a numb开发者_运维百科er are in level 3. All uppercase letters with a number and a lowercase letter are in level 4.
As I'm building the array, is there any way for me to know which level I'm in? The array is being created with a recursive function.
This is a PHP question.
This might be tangential to your question about the array, but you could kill two birds with one stone by using a recursive directory iterator.
$path_to_root = __DIR__;
$directories = new ParentIterator(new RecursiveDirectoryIterator($path_to_root, RecursiveDirectoryIterator::CURRENT_AS_SELF));
$iterator = new RecursiveIteratorIterator($directories, RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $item)
{
printf("%d %s\n", $iterator->getDepth() + 1, $item->getSubPathname());
}
Which would output something like:
1 Root
2 Root/A
3 Root/A/A2
3 Root/A/A3
3 Root/A/A4
4 Root/A/A4/A4a
2 Root/B
3 Root/B/B2
3 Root/B/B3
2 Root/C
2 Root/D
2 Root/E
3 Root/E/E2
4 Root/E/E2/E2a
3 Root/E/E3
As you can see RecursiveIteratorIterator::getDepth()
is used to get the current depth of the recursive iterator, which is the reason for suggesting this approach.
Alternative (if you must use an array)
Assuming your array structure looks something like:
$dirs = array(
'Root' => array(
'A' => array(
'A2' => array(),
'A3' => array(),
'A4' => array(
'A4a' => array(),
),
),
'B' => array(
'B2' => array(),
'B3' => array(),
),
'C' => array(),
'D' => array(),
'E' => array(
'E2' => array(
'E2a' => array(),
),
'E3' => array(),
),
),
);
Then a very similar approach to getting the values from a recursive directory iterator (but this time with a recursive array iterator) can be used. A quick loop over the "parent" arrays can give us the "path" from the current item back to the root.
$recursive = new ParentIterator(new RecursiveArrayiterator($dirs));
$iterator = new RecursiveIteratorIterator($recursive, RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $item)
{
// Build path from "parent" array keys
for ($path = "", $i = 0; $i <= $iterator->getDepth(); $i++) {
$path .= "/" . $iterator->getSubIterator($i)->key();
}
// Output depth and "path"
printf("%d %s\n", $iterator->getDepth() + 1, ltrim($path, "/"));
}
The output would be the same as the earlier one for the directory iterator.
TL;DR We can use recursive iterators from the SPL iterators to make working with recursive/deep structures much simpler.
TL;DR;TL;DR SPL, heck yeah!
One quick an easy answer is to simply add a "depth" parameter to your function and increment it when the function calls itself.
This should do:
function array_depth($array) {
$max_depth = 1;
foreach ($array as $value) {
if (is_array($value)) {
$depth = array_depth($value) + 1;
if ($depth > $max_depth) {
$max_depth = $depth;
}
}
}
return $max_depth;
}
function calc_dimensions(array $array) {
$dimensions = 1;
$max = 0;
foreach ($array as $value) {
if (is_array($value)) {
$subDimensions = calc_dimensions($value);
if ($subDimensions > $max) {
$max = $subDimensions;
}
}
}
return $dimensions+$max;
}
$array = array(
array(
array(
4 => 5,
array(
6 => 6
)
)
),
1 => 5
);
echo calc_dimensions($array)."\n";
Maybe you are asking the wrong question. What is the final goal? For example there is a RecursiveDirectoryIterator class within SPL, maybe that will do for you? Building a big multidimensional array will eat loads of memory, so maybe simply iterating over all those files recursively would suffice?
精彩评论