Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to increment depth variable in recursion? It keeps resetting

Tags:

php

I have a question like this:

Create a function that takes in a nested array and an element and returns the frequency of that element by nested level.

Example:

freqCount([1, 4, 4, [1, 1, [1, 2, 1, 1]]], 1) ➞ [[0, 1], [1, 2], [2,3]] // The array has one 1 at level 0, 2 1's at level 1, and 3 1's at level 2.

So I have to use recursion since we don't know how many levels there are. I am getting the right number of occurrences of the $el passed but not the right level of depth because $depth keeps getting reset on every new call of recurse();

Here is the basic code:

<?php

function freqCount($arr, $el) {

recurse($arr, $el);

}

function recurse($a, $e) {

   $counter = 0;
     $depth = 0;
    $result = [];

    foreach($a as $k => $v) {
        if(!is_array($v) && $v === $e) {
            $counter++;
            $result[$depth] = $counter;
        } elseif(is_array($v)) {
            $depth++;
            recurse($v, $e);
        } else {
            continue;
        }
    }

    echo "<pre>";
    print_r($result);

}

Outputs:

Array
(
    [0] => 3 // Should be [2] => 3
)

Array
(
    [0] => 2 // Should be [1] => 2
)

Array
(
    [0] => 1
)
like image 905
rec0nstr Avatar asked Jun 06 '26 09:06

rec0nstr


2 Answers

Your depth variable is locally scoped to the function and gets set to 0 each time the function is called. You need to pass the depth variable down the recursion so that it increments properly. Something like:

<?php

function freqCount($arr, $el) {
$depth = 0;
recurse($arr, $el, $depth);

}

function recurse($a, $e, $depth) {

    $counter = 0;
    $result = [];
    
    foreach($a as $k => $v) {
        if(!is_array($v) && $v === $e) {
            $counter++;
            $result[$depth] = $counter;
        } elseif(is_array($v)) {
            $depth++;
            recurse($v, $e, $depth);
        } else {
            continue;
        }
    }

    echo "<pre>";
    print_r($result);

}
like image 129
Patrick Kelly Avatar answered Jun 07 '26 23:06

Patrick Kelly


Here's a possible simplified, PHP 7.4 version of what you're looking for:

function freqCount(array $values, $searchValue): array
{
    $frequencies = computeFrequencies($values, $searchValue, 0);

    return array_map(
        static fn (int $depth) => [$depth, $frequencies[$depth]],
        array_keys($frequencies)
    );
}

function computeFrequencies(array $values, $searchValue, int $depth): array
{
    $frequencies = [$depth => 0];

    foreach ($values as $value) {
        if ($value === $searchValue) {
            $frequencies[$depth]++;
        } elseif (is_array($value)) {
            foreach (computeFrequencies($value, $searchValue, $depth + 1) as $deeperDepth => $frequency) {
                $frequencies[$deeperDepth] = ($frequencies[$deeperDepth] ?? 0) + $frequency;
            }
        }
    }

    return $frequencies;
}

Usage:

print_r(freqCount([1, 4, 4, [1, 1, [1, 2, 1, 1]]], 1));  // [[0, 1], [1, 2], [2, 3]]
print_r(freqCount([1, [2], 1, [[2]], 1, [[[2]]], 1, [[[[2]]]]], 2));  // [[0, 0], [1, 1], [2, 1], [3, 1], [4, 1]]

It basically splits the task into two functions:

  • computeFrequencies is the "private" recursive one, it takes a $depth parameter and returns a level => occurrences associative array,
  • freqCount simply calls it once with $depth = 0, lets it do its thing then transforms the result into the desired output.

Demo (PHP 7.4)

Demo (PHP 7.2+)

like image 20
Jeto Avatar answered Jun 07 '26 21:06

Jeto



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!