Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 476
Bryan Downing Avatar asked Aug 26 '10 19:08

Bryan Downing


2 Answers

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!

like image 150
salathe Avatar answered Oct 22 '22 23:10

salathe


One quick an easy answer is to simply add a "depth" parameter to your function and increment it when the function calls itself.

like image 40
Basic Avatar answered Oct 23 '22 00:10

Basic