1

I'm working on an algorithm to calculate the amount of levels in an array of arrays.

The reason I need this is because I need to fetch a list of categories from the database that belongs to a category parent, and depending of the amount of levels this array has, I need to display an amount of category lists (to select categories).

So it would be a category list for each level of categories, for example

Vehicles
        Cars
            honda
                   Red
                   Blue
                   Yellow
            ford
                   Red
            suzuki
                   Red
                   Green
            BMW
        Motorcycles
            bla bla 
                 bla bla 
Groceries
        Fruits
            Berries
                    Red
                        Strawberries

So I need a function to check the amount of levels of the selected parent, for example if i pass the ID of vehicles i want it to return 4 or 3 if we count Vehicles as level 0, so I know that if the client selected Vechicles from the first list I will have to display 3 more lists.

So far, what I have that is not working is

function count_children_level($list_of_children, $start_depth = 0){    

    // if the data being passed is an array
    if(is_array($list_of_children)){

        // amount of nodes is equal to the 
        $max = $start_depth;

        foreach($list_of_children as $i){

            $result = count_children_level($i, $start_depth + 1);

            if ($result > $max){

                $max = $result;
            }
        }
        return $max;
    }
    //if is not array
    else {
        return $start_depth;
    }
}

I really need to understand how this works because i have to work with several functions like this one, so please if you can, explain your answer in detail.

Thanks

3 Answers 3

2

The depth of a nested array is equal to the depth of the largest array in it + 1.

So for your recursive function, instead of passing the entire array every time, you can make an actual recursive call that only gets the depth of the sub-array. So this function returns 1 for a normal, flat array and 1 extra for each level.

<?php
function array_depth($array) {
  // Determine largest sub-array. Start with 0 if there are no arrays at all.
  $max = 0;
  foreach ($array as $item) {
    if (is_array($item)) {
      // Make the recursive call, passing not $array, but the sub-array ($item)
      // to the function again.
      $depth = array_depth($item);
      if ($depth > $max)
        $max = $depth;
    }
  }
  // Depth of this array is the depth of the largest sub-array + 1.
  return $max + 1;
}

I called it like this:

echo array_depth(
  array('x' => 
    array('y' => 
      array('z'))));  // Returns 3.
Sign up to request clarification or add additional context in comments.

4 Comments

Hi GolezTrol, thank you very much for your answer, could you please explain it a little bit?
Can you post the array you used and add it to your question? I'll check my code with your array and fix it where needed, or explain what is going wrong.
You are right, it works as intended but the array I'm passing probably has only two levels, the thing is i dont need to know the depth of the array but the depth of the categories because what im fetching from the database is a 1 level array that has the category structure specified within the category_id and category_parent, so its going to be a lot more complicated than i thought to get the depth
Ah, I see. Well, that can be fixed too, but if you need help, I think you'd better ask a new question, otherwise this one will become a mess. Make sure to post the array structure as you got it, to make it clear.
2

My interpretation of what @GolezTrol said in their answer ("The depth of a nested array is equal to the depth of the largest array in it + 1"):

function array_depth($a)
{
    // If $a is not an array or it's an empty array then its depth is 1
    if (! is_array($a) || count($a) == 0) {
        return 0;
    }

    // Otherwise, add 1 to the maximum depth of the elements it contains
    return 1 + max(array_map('array_depth', $a));
}

1 Comment

It should return 0; when an item is not an array. But apart from that, this code works fine. :) Checking for empty arrays is an interesting addition. It depends on your definition whether you want to count an empty array as an extra level.
0

Another solution with the RecursiveIteratorIterator class. In this way you don't need a recursive function:

$array = array(
    'Vehicles' => array(
        'Cars' => array(
            'honda' => array(
                'Red',
                'Blue',
                'Yellow',
            )
        )
    )
);

function getTotalDepth($array) {
    $iterator = new RecursiveIteratorIterator(
        new RecursiveArrayIterator($array)
    );
    $max = 0;
    foreach ($iterator as $element) {
        if (!$iterator->callHasChildren()) {
            $max = max($max, $iterator->getDepth());
        }
    }
    return $max;
}

echo getTotalDepth($array);

Also very helpful if you want to iterate the complete array:

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

foreach ($iterator as $element) {
    print_r($element);
    echo '<br>';
}

Comments

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.