0

I have a multi-dimensional array that looks something like the following:

array ( 
    0 => array ( 'text' => 'LEVEL 0-0', 'children' => 
    array ( 
        0 => array ( 'text' => 'LEVEL 1-0 0', 'children' =>
        array ( 
            0 => array ( 'text' => 'LEVEL 2-0 0', 'children' => 
            array ( 
                0 => array ( 'text' => 'LEVEL 3-0 0', ), 
                1 => array ( 'text' => 'LEVEL 3-1 0', ), 
                2 => array ( 'text' => 'LEVEL 3-2 0', ), 
                3 => array ( 'text' => 'LEVEL 3-3 0', ), 
                4 => array ( 'text' => 'LEVEL 3-4 0', ), 
                5 => array ( 'text' => 'LEVEL 3-5 0', ), ), ), 
            1 => array ( 'text' => 'LEVEL 2-1 0', ), 
            2 => array ( 'text' => 'LEVEL 2-2 0', 'children' => 
                array ( 
                0 => array ( 'text' => 'LEVEL 3-0 2', ), ), ), 
            3 => array ( 'text' => 'LEVEL 2-3 0', ), 
            4 => array ( 'text' => 'LEVEL 2-4 0', ), 
            5 => array ( 'text' => 'LEVEL 2-5 0', 'children' => 
            array ( 
                0 => array ( 'text' => 'LEVEL 3-0 5', ), 
                1 => array ( 'text' => 'LEVEL 3-1 5', ), 
                2 => array ( 'text' => 'LEVEL 3-2 5', ), 
                3 => array ( 'text' => 'LEVEL 3-3 5', ), 
                4 => array ( 'text' => 'LEVEL 3-4 5', ), 
                5 => array ( 'text' => 'LEVEL 3-5 5', ), ), ), 
            6 => array ( 'text' => 'LEVEL 2-6 0', ), 
            7 => array ( 'text' => 'LEVEL 2-7 0', ), ), ), 
        ), 
    ), 
)

How can I count and check if an array is the final array in an array?

Let's say we have a counter $i = 0;.

Whenever an array has children, we want the the counter to increment.

if (!empty($value['children'])) { $i++; }

Whenever we reach the final array in an array, we want the counter to decrement.

pseudo-code if (final array in array) { $i--; }

Our ending count should be $i = 0;.

AlexanderGR
  • 69
  • 1
  • 9
  • 1
    Possible duplicate of [Checking during array iteration, if the current element is the last element](https://stackoverflow.com/questions/6092054/checking-during-array-iteration-if-the-current-element-is-the-last-element) – Patrick Q Nov 25 '19 at 21:59
  • @PatrickQ Nope. That question is asking how to find the last element in a single-dimensional array. I am asking how to find the last array in a multi-dimensional array. – AlexanderGR Nov 25 '19 at 23:11
  • 1
    Please always provide array/object data from `var_export()` or as a json encoded string. I find your input and desired output to be Unclear. – mickmackusa Nov 26 '19 at 04:28
  • @AlexanderGR The logic is the same. As you noted, you already have code that iterates through your multi-dimensional array. You just apply the check at each level. A multi-dimensional array is just an array of (at some point) single-dimensional arrays. – Patrick Q Nov 26 '19 at 12:52
  • @PatrickQ The goal is not at all finding the elements of an array. Finding the last element will get each and every end of an array, but I want to get ONLY the end of an array of arrays. As posed in the question, it should only get every line where `final array***` is written. Think of the question more to do with the PHP array() function and counting the instances of using said function. – AlexanderGR Nov 26 '19 at 16:44
  • @AlexanderGR I'm not sure how else to explain it. You already know how to recursively iterate through multi-dimensional arrays. Your question was how to find the last child of a parent, which is really just asking how to get the last element of an array, which is what the duplicate does. In fact, DontPanic's answer below utilizes the answer in the linked duplicate (see the "Update3" section) together with your existing logic, which was my whole point. – Patrick Q Nov 26 '19 at 17:07
  • @PatrickQ `array[element] !== array(array)` Is there a way to treat the `array()` function itself as an element? `array[array()]` – AlexanderGR Nov 26 '19 at 18:28
  • @AlexanderGR This has been requested of you multiple times across both this and the related question, _please_ provide a _runnable_ version of your sample array so that we do not have to spend our time to re-create it to provide you an answer. – Patrick Q Nov 26 '19 at 18:39
  • @PatrickQ Included in EDIT 2. – AlexanderGR Nov 26 '19 at 18:50
  • I can still see my comment that requests either `var_export()` or `json_encode()`ed data. You see my comment, right? I'm trying to withhold the urge to close your Unclear question. We expect you to create a **minimal** yet realistic representation of your data AND show us your **exact desired output based on your minimal yet realistic input data**. I'll give you a little more time to edit your question to include tthse vital pieces of information (not make us go to some other website to see the data). – mickmackusa Nov 27 '19 at 09:37
  • Cut down the data. It only needs to be long enough to represent the necessity for recursion. 3 levels of data. Some subarrays not going the full depth. Yes, this asks more effort from you as a poster, but this is the expected standard of questions here to ensure quality. Show a minimal sample and your desired result (I don't know where/how you want to store the child counts for each level. Please edit your question to remove all of the earlier question bloat and form a clear, concise, and non-rambling question for the benefit of volunteers and researchers. – mickmackusa Nov 27 '19 at 22:10
  • @mickmackusa That's fair and understandable. Even though this question is solved, I made the changes for documentation purposes. – AlexanderGR Nov 28 '19 at 00:08
  • It remains unclear how you want to store the count. Do you want to write the count into each subarray? Why won't you comply with my requests for question completion? – mickmackusa Nov 28 '19 at 00:34

1 Answers1

1

You can use array_key_last() to find the key of the final element in an array before iterating it. This can be applied to any number of array dimensions.

This example will output the text for each node in your example tree and indicate whether that node is the final array element.

function listElements(array $input)
{
    $final = array_key_last($input);
    $n = count($input);
    foreach ($input as $key => $element) {
        echo $element['text'], ($key == $final) ? " last of $n" : '', PHP_EOL;
        if (isset($element['children'])) {
            listElements($element['children']);
        }
    }
}

(This uses the same approach shown in the most recent update of this answer to the proposed duplicate. I'm just showing here how it can still work when applied recursively.)


Based on your edit it looks like the $i you're referring to corresponds to recursion depth. You can keep track of that by adding the depth to the function signature and incrementing it in the recursive call. Here is an example using PHP 5.6 syntax with end()/key() rather than array_key_last().

function listElements(array $input, $depth = 0)
{
    end($input);
    $final = key($input);
    $n = count($input);
    foreach ($input as $key => $element) {
        echo $element['text'];
        echo ($key == $final) ? " last of $n," : '';
        echo " depth $depth", PHP_EOL;
        if (isset($element['children'])) {
            listElements($element['children'], $depth + 1);
        }
    }
}

Working example at https://3v4l.org/J9fek

Don't Panic
  • 41,125
  • 10
  • 61
  • 80
  • This is useful and functionally solves the problem, but it doesn't actually _count_ each `Array`. – AlexanderGR Nov 26 '19 at 00:58
  • Ah, I incorrectly assumed the count was only there because you were thinking it was needed to determine the last element. I can edit the answer to suggest a way to add a count – Don't Panic Nov 26 '19 at 01:01
  • Okay, updated to include count. I haven't tested the updated code, but I think it should work okay. – Don't Panic Nov 26 '19 at 01:05
  • This is still counting the elements. Is there a way to count the instances of the PHP `array()` function itself? – AlexanderGR Nov 26 '19 at 16:46
  • But every element here is an array, right? Sorry, I think I'm still not understanding exactly what you're asking. Can you show a small example array and what the count should be for it? The example in your question clearly shows what you meant by final array, but doesn't really address the count aspect unless I missed something. Which is always possible ;-) – Don't Panic Nov 26 '19 at 16:56
  • I updated the question with a simplified array and further explanation. Thanks for your patience. I'm afraid I'm not being as clear as possible. – AlexanderGR Nov 26 '19 at 18:22
  • I should also include that my working environment requires I use PHP 5.6.4 which doesn't support some of the functions you use. P.S. I have edited the question to included a link to the actual array that I'm working with. – AlexanderGR Nov 26 '19 at 18:53
  • @AlexanderGR I updated the answer based on my impression after your edits. Hopefully that is closer to what you were going for. By the way, when people in the comments are referring to runnable examples of your data, they mean in a format we can copy/paste and easily work with, like JSON or var_export. var_dump/print_r output generally requires time-consuming manual parsing before we can use it. – Don't Panic Nov 26 '19 at 21:51
  • I'm going to take this answer because functionally it does exactly the same thing of what I requested. I'm still relatively new to PHP so this question was probably pedantic, so thank you for your time and for explaining some new things to me! – AlexanderGR Nov 27 '19 at 16:55