GrumpyCrouton
GrumpyCrouton

Reputation: 8621

Recursive function only works for first level of array

I wrote a recursive function which relies on echo to work, and it works perfectly. But, to challenge myself, I wanted to make it return an array of processed values instead of echoing the values directly.

printAll(
    json_decode('[{"id":1,"children":[{"id":2},{"id":5,"children":[{"id":3}]}]},{"id":4}]', true)
);

function printAll($a, $level = '', $values = []) {
    foreach($a as $v) {
        $values[] = $value = "{$level}{$v['id']}";
        if(!empty($v['children'])) {
            return printAll($v['children'], "{$value}.", $values);
        }
    }
    return $values;
}

But I'm getting unexpected results. This function currently returns an array that looks like this:

Array
(
    [0] => 1
    [1] => 1.2
    [2] => 1.5
    [3] => 1.5.3
)

But in this case, I'm expecting this:

Array
(
    [0] => 1
    [1] => 1.2
    [2] => 1.5
    [3] => 1.5.3
    [4] => 4
)

It looks like my recursive function only processes the very first value of $data and all of it's children, but never the rest of $data. I'm assuming this is because I am using return which ends the loop.

My question is, how can I make my printAll() function process the entire set of data, without overly complicating the function?

Upvotes: 1

Views: 242

Answers (2)

Felippe Duarte
Felippe Duarte

Reputation: 15131

You need to remove the return printAll(...) and add the value to the variable. Otherwise it will stop in the first value that has a 'children'

<?php

function printAll($a, $level = '', $values = []) {
    foreach($a as $v) {
        $values[] = $value = "{$level}{$v['id']}";
        if(!empty($v['children'])) {
            //Just remove this return and add to the variable you already have.
            $values = printAll($v['children'], "{$value}.", $values);
        }
    }
    return $values;
}

$a = json_decode('[{"id":1,"children":[{"id":2},{"id":5,"children":[{"id":3}]}]},{"id":4}]',true);
var_dump(printAll($a));

Upvotes: 1

Nigel Ren
Nigel Ren

Reputation: 57121

The problem is that as you have

return printAll($v['children'], "{$value}.", $values);

part of the way through, this will ignore any further items in subsequent elements.

A quick fix would be to just add the new values into the current values and have the 1 return at the end of the routine...

$values += printAll($v['children'], "{$value}.", $values);

Upvotes: 3

Related Questions